{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Express sklearn pipeline as codeflare pipeline\n",
    "Reference: https://scikit-learn.org/stable/auto_examples/neural_networks/plot_rbm_logistic_classification.html#sphx-glr-auto-examples-neural-networks-plot-rbm-logistic-classification-py"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Automatically created module for IPython interactive environment\n",
      "[BernoulliRBM] Iteration 1, pseudo-likelihood = -25.57, time = 0.11s\n",
      "[BernoulliRBM] Iteration 2, pseudo-likelihood = -23.68, time = 0.18s\n",
      "[BernoulliRBM] Iteration 3, pseudo-likelihood = -22.74, time = 0.18s\n",
      "[BernoulliRBM] Iteration 4, pseudo-likelihood = -21.83, time = 0.16s\n",
      "[BernoulliRBM] Iteration 5, pseudo-likelihood = -21.62, time = 0.16s\n",
      "[BernoulliRBM] Iteration 6, pseudo-likelihood = -21.11, time = 0.15s\n",
      "[BernoulliRBM] Iteration 7, pseudo-likelihood = -20.88, time = 0.15s\n",
      "[BernoulliRBM] Iteration 8, pseudo-likelihood = -20.58, time = 0.13s\n",
      "[BernoulliRBM] Iteration 9, pseudo-likelihood = -20.32, time = 0.14s\n",
      "[BernoulliRBM] Iteration 10, pseudo-likelihood = -20.13, time = 0.14s\n",
      "Logistic regression using RBM features:\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "           0       0.99      0.98      0.99       174\n",
      "           1       0.91      0.93      0.92       184\n",
      "           2       0.94      0.95      0.95       166\n",
      "           3       0.95      0.88      0.91       194\n",
      "           4       0.95      0.95      0.95       186\n",
      "           5       0.94      0.92      0.93       181\n",
      "           6       0.98      0.98      0.98       207\n",
      "           7       0.93      0.98      0.96       154\n",
      "           8       0.92      0.89      0.90       182\n",
      "           9       0.86      0.92      0.89       169\n",
      "\n",
      "    accuracy                           0.94      1797\n",
      "   macro avg       0.94      0.94      0.94      1797\n",
      "weighted avg       0.94      0.94      0.94      1797\n",
      "\n",
      "\n",
      "Logistic regression using raw pixel features:\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "           0       0.90      0.93      0.91       174\n",
      "           1       0.59      0.57      0.58       184\n",
      "           2       0.75      0.86      0.80       166\n",
      "           3       0.78      0.78      0.78       194\n",
      "           4       0.82      0.83      0.82       186\n",
      "           5       0.77      0.77      0.77       181\n",
      "           6       0.91      0.87      0.89       207\n",
      "           7       0.86      0.88      0.87       154\n",
      "           8       0.67      0.57      0.61       182\n",
      "           9       0.74      0.77      0.76       169\n",
      "\n",
      "    accuracy                           0.78      1797\n",
      "   macro avg       0.78      0.78      0.78      1797\n",
      "weighted avg       0.78      0.78      0.78      1797\n",
      "\n",
      "\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 302.4x288 with 100 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "print(__doc__)\n",
    "\n",
    "# Authors: Yann N. Dauphin, Vlad Niculae, Gabriel Synnaeve\n",
    "# License: BSD\n",
    "\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "from scipy.ndimage import convolve\n",
    "from sklearn import linear_model, datasets, metrics\n",
    "from sklearn.model_selection import train_test_split\n",
    "from sklearn.neural_network import BernoulliRBM\n",
    "from sklearn.pipeline import Pipeline\n",
    "from sklearn.preprocessing import minmax_scale\n",
    "from sklearn.base import clone\n",
    "\n",
    "\n",
    "# #############################################################################\n",
    "# Setting up\n",
    "\n",
    "def nudge_dataset(X, Y):\n",
    "    \"\"\"\n",
    "    This produces a dataset 5 times bigger than the original one,\n",
    "    by moving the 8x8 images in X around by 1px to left, right, down, up\n",
    "    \"\"\"\n",
    "    direction_vectors = [\n",
    "        [[0, 1, 0],\n",
    "         [0, 0, 0],\n",
    "         [0, 0, 0]],\n",
    "\n",
    "        [[0, 0, 0],\n",
    "         [1, 0, 0],\n",
    "         [0, 0, 0]],\n",
    "\n",
    "        [[0, 0, 0],\n",
    "         [0, 0, 1],\n",
    "         [0, 0, 0]],\n",
    "\n",
    "        [[0, 0, 0],\n",
    "         [0, 0, 0],\n",
    "         [0, 1, 0]]]\n",
    "\n",
    "    def shift(x, w):\n",
    "        return convolve(x.reshape((8, 8)), mode='constant', weights=w).ravel()\n",
    "\n",
    "    X = np.concatenate([X] +\n",
    "                       [np.apply_along_axis(shift, 1, X, vector)\n",
    "                        for vector in direction_vectors])\n",
    "    Y = np.concatenate([Y for _ in range(5)], axis=0)\n",
    "    return X, Y\n",
    "\n",
    "\n",
    "# Load Data\n",
    "X, y = datasets.load_digits(return_X_y=True)\n",
    "X = np.asarray(X, 'float32')\n",
    "X, Y = nudge_dataset(X, y)\n",
    "X = minmax_scale(X, feature_range=(0, 1))  # 0-1 scaling\n",
    "\n",
    "X_train, X_test, Y_train, Y_test = train_test_split(\n",
    "    X, Y, test_size=0.2, random_state=0)\n",
    "\n",
    "# Models we will use\n",
    "logistic = linear_model.LogisticRegression(solver='newton-cg', tol=1)\n",
    "rbm = BernoulliRBM(random_state=0, verbose=True)\n",
    "\n",
    "rbm_features_classifier = Pipeline(\n",
    "    steps=[('rbm', rbm), ('logistic', logistic)])\n",
    "\n",
    "# #############################################################################\n",
    "# Training\n",
    "\n",
    "# Hyper-parameters. These were set by cross-validation,\n",
    "# using a GridSearchCV. Here we are not performing cross-validation to\n",
    "# save time.\n",
    "rbm.learning_rate = 0.06\n",
    "rbm.n_iter = 10\n",
    "# More components tend to give better prediction performance, but larger\n",
    "# fitting time\n",
    "rbm.n_components = 100\n",
    "logistic.C = 6000\n",
    "\n",
    "# Training RBM-Logistic Pipeline\n",
    "rbm_features_classifier.fit(X_train, Y_train)\n",
    "\n",
    "# Training the Logistic regression classifier directly on the pixel\n",
    "raw_pixel_classifier = clone(logistic)\n",
    "raw_pixel_classifier.C = 100.\n",
    "raw_pixel_classifier.fit(X_train, Y_train)\n",
    "\n",
    "# #############################################################################\n",
    "# Evaluation\n",
    "\n",
    "Y_pred = rbm_features_classifier.predict(X_test)\n",
    "print(\"Logistic regression using RBM features:\\n%s\\n\" % (\n",
    "    metrics.classification_report(Y_test, Y_pred)))\n",
    "\n",
    "Y_pred = raw_pixel_classifier.predict(X_test)\n",
    "print(\"Logistic regression using raw pixel features:\\n%s\\n\" % (\n",
    "    metrics.classification_report(Y_test, Y_pred)))\n",
    "\n",
    "# #############################################################################\n",
    "# Plotting\n",
    "\n",
    "plt.figure(figsize=(4.2, 4))\n",
    "for i, comp in enumerate(rbm.components_):\n",
    "    plt.subplot(10, 10, i + 1)\n",
    "    plt.imshow(comp.reshape((8, 8)), cmap=plt.cm.gray_r,\n",
    "               interpolation='nearest')\n",
    "    plt.xticks(())\n",
    "    plt.yticks(())\n",
    "plt.suptitle('100 components extracted by RBM', fontsize=16)\n",
    "plt.subplots_adjust(0.08, 0.02, 0.92, 0.85, 0.08, 0.23)\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "2021-06-09 10:48:44,778\tINFO services.py:1267 -- View the Ray dashboard at \u001b[1m\u001b[32mhttp://127.0.0.1:8266\u001b[39m\u001b[22m\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[2m\u001b[36m(pid=4523)\u001b[0m [BernoulliRBM] Iteration 1, pseudo-likelihood = -25.57, time = 0.11s\n",
      "\u001b[2m\u001b[36m(pid=4523)\u001b[0m [BernoulliRBM] Iteration 1, pseudo-likelihood = -25.57, time = 0.11s\n",
      "\u001b[2m\u001b[36m(pid=4523)\u001b[0m [BernoulliRBM] Iteration 1, pseudo-likelihood = -25.57, time = 0.11s\n",
      "\u001b[2m\u001b[36m(pid=4523)\u001b[0m [BernoulliRBM] Iteration 1, pseudo-likelihood = -25.57, time = 0.11s\n",
      "\u001b[2m\u001b[36m(pid=4523)\u001b[0m [BernoulliRBM] Iteration 2, pseudo-likelihood = -23.68, time = 0.15s\n",
      "\u001b[2m\u001b[36m(pid=4523)\u001b[0m [BernoulliRBM] Iteration 2, pseudo-likelihood = -23.68, time = 0.15s\n",
      "\u001b[2m\u001b[36m(pid=4523)\u001b[0m [BernoulliRBM] Iteration 2, pseudo-likelihood = -23.68, time = 0.15s\n",
      "\u001b[2m\u001b[36m(pid=4523)\u001b[0m [BernoulliRBM] Iteration 2, pseudo-likelihood = -23.68, time = 0.15s\n",
      "\u001b[2m\u001b[36m(pid=4523)\u001b[0m [BernoulliRBM] Iteration 3, pseudo-likelihood = -22.74, time = 0.15s\n",
      "\u001b[2m\u001b[36m(pid=4523)\u001b[0m [BernoulliRBM] Iteration 3, pseudo-likelihood = -22.74, time = 0.15s\n",
      "\u001b[2m\u001b[36m(pid=4523)\u001b[0m [BernoulliRBM] Iteration 3, pseudo-likelihood = -22.74, time = 0.15s\n",
      "\u001b[2m\u001b[36m(pid=4523)\u001b[0m [BernoulliRBM] Iteration 3, pseudo-likelihood = -22.74, time = 0.15s\n",
      "\u001b[2m\u001b[36m(pid=4523)\u001b[0m [BernoulliRBM] Iteration 4, pseudo-likelihood = -21.83, time = 0.14s\n",
      "\u001b[2m\u001b[36m(pid=4523)\u001b[0m [BernoulliRBM] Iteration 4, pseudo-likelihood = -21.83, time = 0.14s\n",
      "\u001b[2m\u001b[36m(pid=4523)\u001b[0m [BernoulliRBM] Iteration 4, pseudo-likelihood = -21.83, time = 0.14s\n",
      "\u001b[2m\u001b[36m(pid=4523)\u001b[0m [BernoulliRBM] Iteration 4, pseudo-likelihood = -21.83, time = 0.14s\n",
      "\u001b[2m\u001b[36m(pid=4523)\u001b[0m [BernoulliRBM] Iteration 5, pseudo-likelihood = -21.62, time = 0.15s\n",
      "\u001b[2m\u001b[36m(pid=4523)\u001b[0m [BernoulliRBM] Iteration 5, pseudo-likelihood = -21.62, time = 0.15s\n",
      "\u001b[2m\u001b[36m(pid=4523)\u001b[0m [BernoulliRBM] Iteration 5, pseudo-likelihood = -21.62, time = 0.15s\n",
      "\u001b[2m\u001b[36m(pid=4523)\u001b[0m [BernoulliRBM] Iteration 5, pseudo-likelihood = -21.62, time = 0.15s\n",
      "\u001b[2m\u001b[36m(pid=4523)\u001b[0m [BernoulliRBM] Iteration 6, pseudo-likelihood = -21.11, time = 0.14s\n",
      "\u001b[2m\u001b[36m(pid=4523)\u001b[0m [BernoulliRBM] Iteration 6, pseudo-likelihood = -21.11, time = 0.14s\n",
      "\u001b[2m\u001b[36m(pid=4523)\u001b[0m [BernoulliRBM] Iteration 6, pseudo-likelihood = -21.11, time = 0.14s\n",
      "\u001b[2m\u001b[36m(pid=4523)\u001b[0m [BernoulliRBM] Iteration 6, pseudo-likelihood = -21.11, time = 0.14s\n",
      "\u001b[2m\u001b[36m(pid=4523)\u001b[0m [BernoulliRBM] Iteration 7, pseudo-likelihood = -20.88, time = 0.15s\n",
      "\u001b[2m\u001b[36m(pid=4523)\u001b[0m [BernoulliRBM] Iteration 7, pseudo-likelihood = -20.88, time = 0.15s\n",
      "\u001b[2m\u001b[36m(pid=4523)\u001b[0m [BernoulliRBM] Iteration 7, pseudo-likelihood = -20.88, time = 0.15s\n",
      "\u001b[2m\u001b[36m(pid=4523)\u001b[0m [BernoulliRBM] Iteration 7, pseudo-likelihood = -20.88, time = 0.15s\n",
      "\u001b[2m\u001b[36m(pid=4523)\u001b[0m [BernoulliRBM] Iteration 8, pseudo-likelihood = -20.58, time = 0.15s\n",
      "\u001b[2m\u001b[36m(pid=4523)\u001b[0m [BernoulliRBM] Iteration 8, pseudo-likelihood = -20.58, time = 0.15s\n",
      "\u001b[2m\u001b[36m(pid=4523)\u001b[0m [BernoulliRBM] Iteration 8, pseudo-likelihood = -20.58, time = 0.15s\n",
      "\u001b[2m\u001b[36m(pid=4523)\u001b[0m [BernoulliRBM] Iteration 8, pseudo-likelihood = -20.58, time = 0.15s\n",
      "\u001b[2m\u001b[36m(pid=4523)\u001b[0m [BernoulliRBM] Iteration 9, pseudo-likelihood = -20.32, time = 0.13s\n",
      "\u001b[2m\u001b[36m(pid=4523)\u001b[0m [BernoulliRBM] Iteration 9, pseudo-likelihood = -20.32, time = 0.13s\n",
      "\u001b[2m\u001b[36m(pid=4523)\u001b[0m [BernoulliRBM] Iteration 9, pseudo-likelihood = -20.32, time = 0.13s\n",
      "\u001b[2m\u001b[36m(pid=4523)\u001b[0m [BernoulliRBM] Iteration 9, pseudo-likelihood = -20.32, time = 0.13s\n",
      "\u001b[2m\u001b[36m(pid=4523)\u001b[0m [BernoulliRBM] Iteration 10, pseudo-likelihood = -20.13, time = 0.15s\n",
      "\u001b[2m\u001b[36m(pid=4523)\u001b[0m [BernoulliRBM] Iteration 10, pseudo-likelihood = -20.13, time = 0.15s\n",
      "\u001b[2m\u001b[36m(pid=4523)\u001b[0m [BernoulliRBM] Iteration 10, pseudo-likelihood = -20.13, time = 0.15s\n",
      "\u001b[2m\u001b[36m(pid=4523)\u001b[0m [BernoulliRBM] Iteration 10, pseudo-likelihood = -20.13, time = 0.15s\n",
      "Logistic regression using RBM features:\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "           0       0.99      0.98      0.99       174\n",
      "           1       0.91      0.93      0.92       184\n",
      "           2       0.93      0.95      0.94       166\n",
      "           3       0.96      0.88      0.92       194\n",
      "           4       0.95      0.94      0.95       186\n",
      "           5       0.93      0.92      0.92       181\n",
      "           6       0.98      0.98      0.98       207\n",
      "           7       0.93      0.99      0.96       154\n",
      "           8       0.91      0.88      0.90       182\n",
      "           9       0.87      0.92      0.89       169\n",
      "\n",
      "    accuracy                           0.94      1797\n",
      "   macro avg       0.94      0.94      0.94      1797\n",
      "weighted avg       0.94      0.94      0.94      1797\n",
      "\n",
      "\n",
      "Logistic regression using raw pixel features:\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "           0       0.99      0.98      0.99       174\n",
      "           1       0.88      0.93      0.91       184\n",
      "           2       0.92      0.95      0.94       166\n",
      "           3       0.94      0.88      0.91       194\n",
      "           4       0.97      0.94      0.95       186\n",
      "           5       0.93      0.91      0.92       181\n",
      "           6       0.98      0.97      0.97       207\n",
      "           7       0.93      0.99      0.96       154\n",
      "           8       0.87      0.86      0.87       182\n",
      "           9       0.87      0.90      0.89       169\n",
      "\n",
      "    accuracy                           0.93      1797\n",
      "   macro avg       0.93      0.93      0.93      1797\n",
      "weighted avg       0.93      0.93      0.93      1797\n",
      "\n",
      "\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAASkAAAEmCAYAAAA+z2ZXAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8QVMy6AAAACXBIWXMAAAsTAAALEwEAmpwYAABq0UlEQVR4nO19d5hdVb32u86Z3kvKTCZDIkWqBmlSA0F6C00BEUHhWj4LCA8KqFjupxfFK58FLgheMaAQqQYINRiRJoQOAUJJSCEkJJlkJjPJtLO/P/Z5937XmbXnnOhMOORZ7/PwMFlnn7P2KnvtX3l/v58JggAeHh4exYrUB30DHh4eHsPBH1IeHh5FDX9IeXh4FDX8IeXh4VHU8IeUh4dHUcMfUh4eHkWNvIeUMWaiMeY3xpgnjDE9xpjAGDM54dpGY8x1xphVxphuY8xDxpiPOa6rMMZcboxZbozZkP3tqSMwHo9NhDHmeGPM+R/0fbhgjDnPGHPiB9T3ZGPMD40xW4/w7x6UfYYOynPd9caYpSPZd0IfgfzXY4x51hjzRce1P8y5dsAY844x5vfGmLaEazcYY+odv3WW/M62+e6zEElqWwCfAdAB4B/DDNgAmAXgCADfAHASgFIAfzPGTMy5/PcA/gPApQCOAbAcwP3GmF0LuB+PkcXxAIrykAJwHoAP5JACMBnADwCM6CFVhHgfwD7Z/04DsBbA740xJydcv3/22mkAfgrgaAD3GGNcZ0k/ANfvfB5AV6E3WFLANY8EQTAeAIwx5wA4LOG64xAO4OAgCP6Wvf4JAAsBfBvAN7NtUwB8FsAXgyD4Q7bt7wBeAfDj7O94eGwSjDHlQRD0ftD38SFEXxAET/Ifxpg5AJYAOAfArY7r/xkEwUD2738YYwYBXAtgewCv5lx7O4AzEAol/P12AAcCmAHgrEJuMK8kFQRBppAfQni4vMsDKvvddQDuAjA957p+ADPlugEANwM43BhTPlwnxpgSY8x3jDHzjTEbjTHvG2PuM8bsINdsb4y5wxizNityPmmMOSLndyiS7mCMuT+rni42xnwh+/kZxpjXjDHrjTF/M8Zsk/P9RcaYG40x/2GMeTN7L88aY6Y57vlzxpgXstesMsbcYIxpTfi9U40xr2bvZ54xZn/H7x1ojJljjOnKXne/MWaXnGvmGmMeNcYckr2vHmPMy8aY4+Wa6wGcCaBNxO9F2c9qTKjmLzbG9BpjVmTV9x2QB9k50fH+3hjTJJ/fkF2bSdLWml3LWzgfACYBOF3u7fqctdslO/b1AP6S/ewwY8xsE5oSOOYLjDHphPt8NrtHOowxfzfG7GtCVYz7+EHp/6BCx5i9Zqwx5s/GmM7seGcAaMg3fzm/sa8x5ulsP4uMMd+Qz3bP3td0x/euN8YsdY17OARBsB7AAgBbFfiVzuz/Sx2fzQAwVdcZ4aG1GMAjm3JTBf+H8HQNAEx2fPYkgPsd7d/Ofqcm+++bAbzuuO4z2et2znMPtwIYAPALhKrl8QB+CWBa9vMJCEXYtwF8DsCxAO4DMAjgSPmdH2b7ewmhlHcogDuybT8F8Hj2tz8N4F2EbxC9j0UI3zivAjgle+0TADYC2F6u+1L2N28GcFR2Dlci3Ag1Ob/3DoCnEYrIxwB4DqH43SDXHZ0d/18RHv7Ts/faAaBdrpuLUI1+JTsPRwB4MPvdbbPXbAPgnuz97J397xPZz64FsALA2QCmAjghO+d751mfyxC+hP4bodT9BQDLAPwTQDp7TS2ANwE8BiCN8GU5Jzv+huw1n8je/31yb9vkrN1bAC4BcDCAg7KffQXABQCORKiSXIhQtbgs5z5/kf2N6xDukaMB/CeAUwHUAfg/2c+/If3XFTrG7HX/QPgQfx3A4QD+F+GeCXi/w8zj9dnvLsl+/4hsWwDgLLnuKQCzc77bAKAHwA8L6GNpTlsa4X6/K6edc16OUAOrBLA7gOcBvAwg5bi2FOFzeIl89mp2ns/KXrNt3nNnBA+pBQBuHuY77dl/PwDgScd1h2SvO2CY/g/OXvPNYa75BeRBlIl/HcCzjon8vLQ1Zr+7mhsy2/7N7LWTcg6VPgBbSVstgDUAbpB+VwD4W8497p87juzvdQBolLY9std9VtreBDAn5/fqAKwC8P9yDql+ANtJ2ziEh7VumiEbNdv+MoBfbuL+mJz9/Utz2vfLjuN4adsrO38/QnjQDOSufXZObnT0w7U7N8/9GIQP1Hezc5vKtm+bvc/E8QE4KNvHIf/KGBG+9AIAp+Zcdy8KP6Rc338Q4WFusv8+K3s/uje/mZ3PiQX0sTQ7RyUIX/C/BdAN4JMJc57736vIvjwc15YgNOG8KmseANgOm3BIjSQFwWQ7dbX/K9e5cFj2u9cOc81UhIfgm2wIgmAQwE0AdjXG1OVcf69c14FQqngyCIJOuea17P/bc777ZBAEi+X7XQglk32yTdsjPBj+pF8KguBRhBvtwJzfeyJ7D8RL2f9vBQDGmO0QSj9/MqHaW2KMKUH41nwiO3bFG0EQvCH9rsyOrxBR/mkAZxljLjHG7FGg2nAoQqko9/7+iVAqiO4vCIKnEDpOvovwoPpJEASJjpkE3JHbkFUbrzHGvIPwEOwH8H8RShfjspcdkr3P321if0DhY9wH4eFxW873b96EvpK+vxWANvn3WoSOKOLLAO4JgqAQ72AbwjnqRygN/h+E9uJ/Jly/N4A9AXwSofbTDeABY8z4hOtnANjBGLMnQoP5k7onC8FIHlJrADQ52huz/+8o8Lo1w/TRDGBNEAQbhrmmCaGakIv3EB6EjTntHTn/7ktoA4CKnPYVjn5WIN5AHGfS/eTOgzX2IDYEs18+ZL9HvLH43zEI5yfx97LoxdBxuPANANcA+CLCA2ulMeYKY0zVMN/h/b3puL86x/39GfEb+coC7ikX1rya0MM0C+Fc/F+EkveeAH6SvYTj5n38Ky7+QsfYCqAjCIL+nO+79kwShvt+GwAEQbARwB8AnJ09MA8AsBOAqwvsYyXiQ+ezCB1d/zuM7fGZIAjmBUHwVBAEtyBUkz+CBA9xVlh4AqHZ4FSEh9YmoRDvXqF4BW7P304AFgehQY7XnWCMqQqCoCfnuj6Ei5+EVQCajDGVwxxUawC0ONpbED4Mwx2CmwrX22M8wjcS74V9u+5n3ib2tzr7/4sBPOT4vM/R9i8hu14XA7g4a/g8GaEtpg/Ad/Lc32EYetDr5zxQ/ojwoKhF+FBtKt0gVyLfBqGKfEYQBDdKX8fmXLcq+/82hGaATUGhY1wOoNEYU5pz0CRJHC4M9/1l0vY/CA+J6Qhth4sA3F9gH/1BEHAfPmWMeRbAiwjtbUfn+3IQBCuMMasAfHyYy2YgfAkNQBxmhWIkJalZCL1EkQqTVa2OzX6m15UiNEjzuhKExucHguHdyA8glIbOGeaavwPY2wjhNKuqnALguaxKNlLY24QuVfZTi3Bhn8g2vY7wzXeqfskYsy9Cz9XfN7G/1xFuwJ2zb7Pc/178F8bQi9AImoggCN4JguC/Eaqfuwxz6YMAMgjtdK77WyjXXozQNvdZhNLaCcaYL2/qveWAUl70UBtjSgGcnnPdQ9n7/NIwv8V9mNt/oWN8AqFN8qSc75+KwpH0/cWQQyoIgrcQPhsXInyZXBsU7pW3EATB6wgPlKOyKtqwMKGXegxCZ1USZiJ87i8LgmCThYSCJCkTE7t2z/7/SGPM+wDeD4KAD9oshAtzozHmQoRvmYsRHio/528FQfC8MWYmgP+X3UALAXwVociYu5ksBEHwN2PMbQB+mT0cHkZ44E1FqIPPBXAFQqPcg8aYHyC0E/wfAB9FAW+GTcQKhPr4DxFu6u8AqEbovUAQBIPGmEsBXGOMuRHAjQjf3j8B8AZCMb1gBEEQGGO+BuCvxpgyhG73VQjfrvsilFh/uYljmI9QOv0qQsluYxAEL5mQ4zYL4cG0HqH9bApC6Sfp/t4yxvwMwG+NMdsjPIQ3IrTlHQrguuwafhKhcfVHQRA8AQDGmKsQrusjQRCQbzMfwAHGmGMQqsergiBYNMxYXkVo6/uJCfk7/QC+lXCfVwA4P/timYXQ/rMXgNeCIJiJ0BE0AOCLxpg1CNf39ULHGATBg8aYRxGu/RiE630Khj/kc9EF4Ofy/dMQ2tPOCrKWaMFVCD2+/Qi9iP8OLkN4gF+KUMhQfDI7tymEL9oLEc5donqZtbOe8C/fTT7LenYuXFb9AMDcnOuaEE7QGoTG3DkApjh+rxIhbeA9hAv8T+Txdsh36a1ZgFD1eB/AbNhu/+0B3AlgXfb3nwRwRJIHIqd9EXI8SnB4engdQqnuLYSb+DmEZNbce/4cgBey16wGcAOA1nz9ytz/MKdtHwB3I3wRbMx+92YA+8g1cwE86vi9RQCul39XI3QqdGT7WpRt/1l2POsQGkdfwjBe1Zw+zsjOeTfCA+5VhF6jiQhVu7cQPtzqtq7I9vE8gPJs2w4I3fg92Xu7fri1y362K4BHs99ZitC75PRKI6QrvJhdlzXZOdM5/DJCF/oAcjxyw41RrhmbndsuhMbtGQhVskK9e0sRvnyezq7zO0lrgFDq6gZwSyFrpH0kfPbT7H2SksI5538ZZKkKAPYq5NnKueYsFOjdoxvTYxNhQrLho0EQfO6DvhcPD2PMoQhVvkOCIJjzQd/PSGIkDeceHh6bGSaMhNgaoZnj2S3tgAJ8qhYPjw87vo+Q69eLkIe0xcGrex4eHkUNL0l5eHgUNfwh5eHhUdTwh5SHh0dRwx9SHh4eRQ1/SHl4eBQ1/CHl4eFR1PCHlIeHR1HDH1IeHh5FDX9IeXh4FDX8IeXh4VHU8IeUh4dHUcMfUh4eHkUNf0h5eHgUNfwh5eHhUdTwh5SHh0dRwx9SHh4eRQ1/SHl4eBQ1/CHl4eFR1PCHlIeHR1HDH1IeHh5FDX9IeXh4FDVGve5eU1NT0NbWhs7OzqhtcHAQAFBaWhq1GWMAAKtWrYraurq6AADpdBoAkMlkkMlkTG4fjY2NQVtbG0pK4uGkUuH5q/329vYCgHVdd3d39NvE6tWrVwVBMDa3n8rKyqCurg59fX1DxllWVhb9zd/SSjzl5eUAgObmZgDA0qVLsWbNmiFjaWhoCFpbW7Fu3bqojXPD+wfiudOxcF7Hjx8ftT3//PPOsTQ1NQUTJ06Mflt/s7+/P2pjn9o3x88xAcDChQuH9FNWVhZUVlaip6cnauP9VlZW6nUAgNra2iFj1utefPFF51g4Z1xzIF4D7iH9e2BgIGqrrq4GAFRUVERtS5YscfZTU1MTNDc3W3POe1+7dm3UpvOXez/8bldXFzZs2DBk/WtqaoKmpiZrP1VVVQEAVq9eHbVx37qgz9WqVaucY6mvrw90n+g9un6L8wTE+1rH+dJLLzn7GQmM+iHV1taG22+/HQ8++GDUxgkeN25c1MaD6I9//GPU9tBDDwGIN69uuNw+br31Vuv3uOkeeOCBqG3hwoUAgMbGxqjtmWeeAWAfZjNmzHjH1U9dXR1OPfVULFmyJGrjgk2ePDlqW79+PQD7Ydhmm20AAGeddRYA4KijjnKOpbW1FX/84x8xe/bsqI0b9q233oraxo4N98OYMWOiNs7PBRdcELXV19c7xzJx4kTMnj07mnf2DQDLli2L2t55J/z6ggULojaO/yMf+UjUdsYZZwzpp7KyEvvssw9eeOGFqI2H9E477RS1ce6mTp0atXH99Lq2tjbnWFpbW/GHP/zBOtA2btwIAJg7d27U9ve//x0A8P7770dte++9NwBgu+22i9rOPfdcZz/Nzc246KKLrDnnvd9xxx1Rm85f7v00NTUBAG677TZXF2hqasKFF16ISZMmRW0f//jHAQAzZsyI2p599lkA9ouQ0Ofguuuuc45l/PjxuPLKK62DiS8ibWtrawMA7LnnnlEb9/W7774btU2aNMnZz0hg1A+pTCaD3t5e1NXVRW01NTUAYL35+LDsscceUVvuYnOhXUilUtbbng/53XffHbVxc23YsCFqe/zxxwHA2hRJGBwcRGdnZ3QIAfHbRO+Ni6xv54aGBgDxgaNjV6xfvx6PP/649bb+61//CgB4++23o7bjjjsOALDLLrtEbTy4dK6TEAQBent7rbH88pe/BBAfTEAsnekhTknqiCOOGLaPnp4evPDCC9hhhx2itn322QcA8PDDD0dtvIfDDz88auM+SJonRXl5ObbZZhtLwuVYHn300aiN++61116L2igp6EsmCalUCtXV1dYhxZfcE088EbUdcMABAIDly5dHbX/5y18AAMcccwwA+wWW20dFRYXVx7x58wDYB+6UKVMA2BI8+9h1113zjsUYg5KSEkuS5pq8+OKLUdu2224LAHjyySejtokTJwKIX2qjDW+T8vDwKGr4Q8rDw6OoMerqHrHVVltFf1N1UIMqxd/6+vqo7dhjjwUQi+lXX32187f7+vrw9ttv46WXXoraHnvsMQCxmgXEurqqGsRuu+0W/X3//fcn9rN06VK89957UduECRMAxMZNIFYn1fbFMVB9SipvHwQB+vv7rXt86qmnAMT2DCB2MPB3AXvu8mHDhg14+eWX8dvf/jZqo1qx//77R21UoVVt2nHHHQHE6mUS6uvrcfjhh1v2N6rwVJOAeO7VEM+xdHR0FDQeYwzefPPN6N9XXXUVAFiqJlUjVXH5+1yXfH2UlpZaqhrtbWvWrInauBfUhEBzwOuvv279O6kPdSJQPVX1kWoj9x8AzJw5E0DolMkHmi5U9b3rrrsAxCoeEBvMaRbRzz/5yU/m7Wck4CUpDw+PosaoS1LpdBr19fWWFMC3zhtvvBG10XukHhp6j3Ldt7no7u7GvHnzIo8HEHu6XIZ4NQLTe1TIm7S7uxtPPfWUJTXRO6ReMkoEOhaOgX0n9dfb24sFCxZYv0dDqLq5+bZU4zxdypSIhsPGjRuxYMEC661L4zElJSA2CKvHaL/99gNgG21dqK2txbRp0yzP2fPPPw/ANhzzt1XCWbx4cXSf+ZBKpVBeXm5J5hyDeqUoxbS3t0dtpHqoMyUJxhik02nLQUNJVqUPfk6PLhB7yegZddFYdDy6P7iPVDKjBKhOEu6ZJC+4or+/H++99571zPD5Ouyww6I2akDq3eXfBx54YN5+RgJekvLw8Chq+EPKw8OjqDHq6l5ZWZklXgOxiKrqHtUOVQu33357ALG4q6qNYuPGjZg/f77FVifP5J///GfURuOfiqkUbZWlm4RMJoPOzk5LjaO6oAxx8kjUEExDKP+v6pwinU6jsbHRMpxS9FeiK1UbNSy7WNZJ6O/vx/LlyyOiIBCrXaou0mB+4oknRm1UoZO4PkQqlUJNTQ1eeeWVqI3qjhpdybfR/cDr9tprr7xjSaVSqK2tte6npaUFgK1WcXwrVqyI2rjv8o2FSKfTFneLv6lOkrPPPhuAzfyn04d7MMlxQv6S3g+dCKqGH3300QBsxwlNCYWsf09PD5577jmL/0TOnzLJub/02aPjyMWsHw14ScrDw6OosVkoCLkxQYsWLQJgSxO8Rg2YlLho0FXJRFFSUoLx48dbrGG6ZtV1SoM92bpA7MothNlcVlaGlpYWy2DsMrxSGnQZTvn2SXqTptNpNDQ0RJIAALz88ssAbIM/nQpqYKVh+Omnn847lvLycmy99dY4+OCDrTbAdmG72MVcNzUgu9DX14eFCxdGxnIgph5oSA2lHTXOUrItxHBOaohKMzTCa7wbQ3KUZc3fT3LKKDKZDHp6eiwpl5LUc889F7XRba9rw3XnHnWFzmgf+l1KZGrk3nnnnQHY8Y6UdlSjSAKpLip1UWpSKo+Lvc45S9IGRhpekvLw8Chq+EPKw8OjqDHq6l5/fz9WrFhhGQLnz58PwDZW0kDqMjareO5CXV0dPvWpT1ltVFNUXSAjWY2xVMMK4cmQ96NqF+9NDZjsWw3sZL6T65LEMaqqqsLHP/5xS5WiSqlcHPK7VG1glH+SWpzbz6677moZPzkGVQHp9FDDKdVKVTVc2LBhA+bPnx+x//XedHyMptd0IFT38vUBhPto1apVFvt69913BwBn3zo/XJckp4yCKpLuR6qYjAoAgOuvvx6AvcZUZT/96U8DsLMm5PYxMDBgqWHcT8oOpyFe1XAatBngDAD/+Mc/nP1UVVXhE5/4RPQsAvHz4VJnVf3k/Hl1z8PDwwObKVXL+vXrLbcvpRsa0IE4xkpjrfgdSlxJLs+ysjJMnjzZMvhS+tA+mNZEjaR0wboSfuUilUqhqqrKks7YjzKbybB2GXLz9VNaWorW1lbcc889URu/o1QOGt41zpBG6c985jN5x0LD+Z///OeojfOrEgDn6pZbbonaKEnoG9sFrr2uGw3mNGID8dwoe5qODJVQkxAEAfr6+izJlZQJpZbQgK9rwHUrxHFCSUqZ8ZTENd6Ra6JS7rRp0wDEe2M4aTeTyVixgJSalQnO/GzqbOBYVBJOkqTKy8sxadKkiMoAxCmBNP8XpTM1ppPeo3nVRhNekvLw8Chq+EPKw8OjqGGS+Doj1oEx7wMYqdSik1x5lEe4j83Vz5Y0Fmc/W9JYRqGfLWksif2MBEb9kPLw8PD4d+DVPQ8Pj6KGP6Q8PDyKGv6Q8vDwKGpsjsycQWlpqcVYJbtXc3KTgaz8EfJ1yGxduXIl1q1bN4R+nk6ng5KSEouPQ36PcpXIt1KeFBnH2jZ//nxnocPa2tohxSHJzdH7pp1P04SQW8XPVq5cic7OziFjaW5uDtrb2y1eGX9HGb7kKilni7+tY168eLFzLHV1dcG4ceOc5bl0LOxT27h+ytJ+5plnhvQzZsyYYNKkSVYfXFPlKnF8GhjL76jNdHBwMHFdxowZY3GdXPnMGVWg17EGpGb1BDBsEVLlXrEfLdbJNdFMqvx9jmdgYMBZ6La8vDyoqqqyojG41trG50n3BP9Wbtl7773nHEt1dXXQ1NRkjZvPoP4mx+oanzLTu7q6PrzFQVOpFOrq6qyJ+/73vw/AjtZn5oCPfexjQ9o4ed/61recfQRBEP1HfO973xtyHcl8DDMAgDPPPBOAXUhhp512SiwO+YMf/MC6luENeqjkhsAAcfgCI9p/9KMfOccyfvx4/P73v8eVV14ZtZEUqL/Hh09zMPEgmT59etT27W9/2zmWhoYGnHfeeVauJz4EGrLCQppKsmW9PaZOzv7ekH7a2towa9YsqxgnyYFMDwzEhFolMPK+tLgCErxRY8eOxU9/+lPrpceHSovDcn9odoo777wTgJ13LKmftrY23HTTTVYoyn333QfAXgfWrVNyKj/X/E0ulJaWYuedd7aIqUzhq3UXuZf1Xkiu1bU6//zznWOpr6/H2WefbdXYW7lyJQA7bIzZFm699daojWM4+eSTo7akIqQjAa/ueXh4FDX8IeXh4VHUGHV1r6amBvvtt18U/Q3Eeq7G2n3lK18BYJe7ZoQ2RfckTldpaSkmTpyII488MmpjfJEmvaM6oDYlxvYxBms4DA4OYt26dVYaX2YeOO2006I2ZkngZwBw0EEHAbBTyrrAsvRqa6LaoLYUqoAam/iJT3zCuj7fWNauXWupFbRJqf2B6pnaKZjWeeutty5oLK+++uqQ+9boe6p5qmZS1VfVRbMAKBhTp/tp4cKFAOwMGizx7koKpxVtVHVTMLUvsxzoOFRVpb3NldQxH0pLSzF27FhLjaPtj9kigNgmpfPDOoi6pkno7e3F22+/jXfeibU03qPuH5oxNHkgn1HGwo42vCTl4eFR1Bh1SaqhoQHTp0+3qt3OmDEDgC0ZsCCAehvopdI3yHB9qLdpzpw5Q/pglLgaSRlNzuT5w4GFGNRTSent+OOPj9poTFVvI/PyMGdSUtR9WVkZJk6ciH333Tdqo2Sjbz2+2VQCpJRWSA3BgYEB6+0IxA4FlT6YtUClK0oa+YokpFIpVFdXWxIODeFaQIJSo+b0oqNFc0wNJ0kNDAxYVZHfeustAHEGASA2DLOWoI5LnSFJMMagsrLScjZwTXTO6MDQLAiUEvkcJFVmTqVSqKystDxnLIyhzgZKzVogg95E9Wgmoa+vD4sXL3ZqJ2qgdxVi4HOpUvxowktSHh4eRQ1/SHl4eBQ1Rl3dq66uxr777htVPAHiRF3KV3FVUaFKxLYkw3ltbS2mTp1qqXH87n/8x39EbRRTNaEcDYOFBFoPDAygo6PD4nKRE6XpYJk0TOv7UZ1gWtgklaysrAxtbW2WUZKqgqp7TICnagrnMMnwq2DdNTVWf/SjH7XGpG36m1QH8qkVLH+uffC3VXVZvnz5kLGwLp+qGX/7298S+8pkMlYCOM6FqogPP/wwANukQLVa+9akb7njqaiosMicNDLrd6i+qgGa80jnjVZ+UZSXl2O77baz5pZkV3Wm0GCuyRbpEKKpYzgwgaPLQK97k+vEdMxA7GTQfTKa8JKUh4dHUWOzFGJYtmyZRemnMVYrstLISOoAELtE+eYariBDJpOx0pnylNfiBWTpqtTEt0IhFYzT6TTq6uqsKst0M6sxVWkUBI3UNA4PVzE3nU5bfbCYgL5dXX1wDrUC8XB91NTUWDQJGrj322+/qI00AzXk8t7zOTSAcM20SjLnXln/d911FwCbtU+W9aGHHhq1/ed//qezjyAIMDg4aEkVrFuozovLL78cQEyhAIAzzjgDgL3vfve73zn7YU28k046KWqj4V3nnIZ5nR86NWjIZzGLpPEoKOGo1EPjPB0yQKwpKMs+CRUVFdh2222tcVOaVAcEowV0DUmnoQQ82vCSlIeHR1HDH1IeHh5FjVFX99auXYs77rjDiginCqaltslKVmMcjd8UbZO4RR0dHbj99tstgzh5S3Pnzo3aWDlD2b+nnHIKAFhlzZNQUlKC5uZmyxBMIyOrgQCxWK413zg+OguSDOeDg4Po6OiwGNl0CKjqwhpzqjZQ5VRuURLo0FBGPsV9ZeTzPtXYzL7z1fcjQ1vVF665BktTFVZmOg3DqpolgQZ6LQlO1Y+MeSBWIRkgDcQVWHI5Yy5Q3dO9QnOBOoE4XuVjsToO5y7JvNDf34/33nvP2h+8N1e1IGXPs60Qg3Y6nUZzc7NVGYiseTWbTJ06FQBw1FFHDRkLKyWNNrwk5eHhUdQYdUlq/fr1+Oc//2lVeKUxVGuV0QCtLF1KBHxjJxnON27ciAULFljSGtNJaBwTY+qOOeaYqI0SkKYTSUI6nUZ9fT0eeeSRqI0GU62JxrfgDTfcELXl5gRSd7KCKWeUbsC3pY6fKTbU3Ux2sBo5k1BZWYkddtjBYtrzN5X57aIz0LWer7K0MQZlZWXWutCY7HKxawViur5Vohyun3Q6bUm4lAqUtkBj/SGHHBK10Vmg+y4JrO+njGxKOSrlcl5UGuI8cp8nOU4oSWuKGs6fSpU0pqsEyDEUIuFQ+nTF7pHNDgCf/exnAcQUCiB2QGmV5dGEl6Q8PDyKGv6Q8vDwKGr4unsfXD9b0lic/WxJYxmFfraksST2MxLwdfc8PDyKGl7d8/DwKGr4Q8rDw6Oo4Q8pDw+Posao86QqKyuD+vr6iKMExBwhV606Tc1BjhP///7776Orq2sIOaesrCyoqqqy+D1kp2sKDnJUlO1LdrXa5pYsWeKsIVZVVRU0NDRY3CsGdSoXiHwlZfOyT3Jn1q5di+7u7iFjYW03ZpEE4nnS+WJgq3KDOHfa79KlS51jqampCZqbm62smeTJaPAy51T74ZzqPLz11ltD+mEfOt9ce73H3HXWe9E1fe2115xjaWxsDNra2ix2OddT84zn/jYQc5q0HJZrLEC4NhMmTLDuiVwh3d/8feVJce2YmXPNmjXO9a+rqwvGjh3r5CBpxAV5WcpV4/rrnn/jjTcS6+41NDRYGVf5LCjni2uiAe8cn/bz3HPPfXjr7tXX1+P000/HQw89FLUx748+DFxQJY0xzIEhEpdeeqmzj6qqKkydOtWqIcbJ1Tw4DBdQ0iAnX8l13/jGNxJr1Z1zzjmYMmVK1MaI+Ntvvz1qY40yHR/75AF29dVXO8fS2tqKP/zhD7jqqquiNmYi0NALhlxoCleS/TR84oILLkisIXjxxRfjwgsvjNpIsPzhD38YtXFOlcC42267AYA1D9OnTx/ST3NzMy666CIrjISkRr1HZgbQ32MYjq7pPvvsk1gP7/bbb8dll10WtZEgqoVSCT1QeFhq2MeJJ57o7GfChAmYMWOGlfGCYVe6v3nAKKmSe+FLX/oSAOCKK65wdYGxY8fiZz/7mRXOxWdDDwW+xPQFwOeE6wMAhx56aOJe/trXvmaF7vBZUGIz85oxfAyIX1i6XjU1NaNWd2/UDykmV9PNxrg6rXTxl7/8BUCcmxoAjj76aAD5GecbNmzAyy+/bLFnmZZDNyQ3jz7sTEFSSNoJJgpjQjYgrkry17/+NWpj0VN9+3BheQ9a3TgX6XQan//856N/8+DWuWHSNGUh81AfLg0IMTAwgFWrVlmpUL7whS8AsPOmz5w5c8hYeD/5GOfpdBq1tbXWGvAg1LHwYdb148GsElwSBgcHsXr1auswpGSrUgGlRk1Gx+8k5RxXkEGvkhhZ7D/96U+jNkpaGpnAPcy+XRIeEI534cKFlrTGF5ymy2ESSX258uBPimZQbNy4Ea+99pp1oHGuNHkki4PqM8NDs5B+RgLeJuXh4VHU8IeUh4dHUWPU1T3mBZ8+fXrUxkKhmpqDthVVKygiU/1ISm/BYElmDNTf0eyItD+onYJ2qkJSdRhjUFFRYensL730EgDbJsX70KyJvI4qh4rzCgYxa5Aw54EqLBCrdDqvVCU1RcxwY0mn0zjrrLOiNgaWqj2MAbpqk6C6k48IzLVX2wwNtbqWVAdVLaQquSmlpnRdqU5pgDL3mBYC3ZS88MYYlJaWWuoi1SFX2po99tgj+ptrQ3U3X6oeTWNENV7tjzQXaKoWGs6ZkmY4VFdXY6+99rJS5jCjJ00YQKzSafoXrpMmDRhNeEnKw8OjqDHqklRFRQW22267KHkWEHs61EDHRFqacI3pOliEMsnYWFZWho985CPW2+zmm28GYCeAY7/6RqJnKZ8RmNcYY6z0H8zPrVITq8Ro+g9KanSTq0FXUVpaivHjx1tjoRTGFBlA7MFR1zkro2jSsiQwj7o6L2gE1oKaJ598MgDbbc80IvnKbPf19WHJkiVWWhYa3dXITclEPU38W71uSXBV2KE0oPm6OecqCVFSUPpCEtLpNBobG61Ct3QAaF5xSokqpeQ6TJIkKRrnNY0R97/OD/e1UjnyaRyKyspK7LLLLpZET+eBOnX4t1Z7ojMjqarOSMNLUh4eHkUNf0h5eHgUNUZd3SspKcGYMWMswxsLMqrYTUP3r371q6iN6iANkEncoqqqKuy2226WwZBqENVIALj22msB2CQ7iuQqNidhcHAQXV1dViFQGlxpQAWARx99FIBdoolqBdXZJPWSecFVtL/vvvsAwCp+Sa6WGnyfe+656D4LgTHGUg2pQigJlWRVJRfSaK/lwlwgR45ZMoGYv6QGf86FGuJpENY9koSSkhKMHTvWWkOqMWoE5m+pCYCqv95jEkpLS9HS0mI5fDjXqu5THVSzAq/LV9KM6p6Om84Dl2OBpbL0t3WfJCEIAvT391s57qnSadQHVcC77747aqMzqpC1GQl4ScrDw6OoMeqSVFlZGdrb260Tm6e/Sh80+qnBmG9dSiZJZb3T6TSqq6utNzFZ7fp7ZAXrG4nG1EKYzQMDA1i9erXFTqeExJzqQPym1nLsrCBDCkJS5ZuBgQGsWbMmYq0DsRSj8Xy8b5UA+HYuRCpgyfDZs2dHbSyKqexivlW1XDn7zlcclFKhlhSnM0Hnhkb0Qu7bhSAIsHHjRkvSpsFc54wUC5XqadBWJ04SuP5qOOde0L1MB4/mKadEQvZ4kiTNikQaNUBpkNWOeC8AUFNTE7WR3qGSfhJ6e3vxxhtvWP1Q8lPDO+dK55FSfiFViUYCXpLy8PAoavhDysPDo6ix2Rjnd955Z9RGY+9+++0XtZGnoilPmMmA4m6SStbT04Pnn38+4lUBsVFXRW4aiQ844ICojcbWQtS9VCqF6upqi/9CA7YayakCUMUDYrWTKmsS52twcBDr1q2z1EGqRsotorjvYq6rCpCkIgdBEAXmEjS4apoQOiDGjBkTtdGQq2xnF8jF0WBi3o+qdhyXMvl17vIhk8lgw4YNlvrJfjQAm2qacqIY+K7zrZwwBddGA7CpImnKG+5hV3qbfI4TBrErJ44mBQ3AJrteDfDk76mpIAmZTAZ9fX2WE4ksd1X3OAbdJ+TtaTHW0YSXpDw8PIoaoy5JpdNp1NTUWMxmxpZpKgu+WTTXE13hfIMM57YtLS213pCf+9znANiM7B133BGAbbSl1JPPCMx+UqmUVQiUblhl39I4rJJBbkKyJMM5C1Aqe5qsa5UyGZN2yy23RG18S3OcQDKTmsZmzd91+umnA7BjzihVKFWBEleSlEaUlZVhq622wne+852ojW97l8FWE7Dxba7ScRIGBwfR2dlpOURIR9E4PULpFJQadU9oWqHcftatW2cZjGkw1zQqpChokU3ua0omzDmWCzqBVNLi30pzoPOCUg0Qz6NK9fmgzwf3HHN5AbHBX1PZUJPQNC+FOB7+VXhJysPDo6jhDykPD4+ihi8O+sH1syWNxdnPljSWUehnSxpLYj8jAV8c1MPDo6jh1T0PD4+ihj+kPDw8ihqjTkGorq4OmpqarARwVDFdtbzUNZ9bb27VqlXOunvNzc1Be3u75RInXUFpC+xDiZQkc6oL+YUXXnDWEGNNNK0PR2qBuvrpwlVXLu+D7uTBwUFkMpkhY2lsbAwmTJhgEQFdWQL4uWY8oNteXeSvvvqqcyxNTU3BxIkTLdcy3dq6Buxb54z9aLreZ555Zkg/TU1NQXt7u0UEdCV9I3VCUwWzD420d/UBALW1tcGYMWMsYiJ/S++bn7vqM+bMrbOfysrKoK6uzpozfl8zMPC3lBTJPZyvhiRr++m+dVVn4bpoxgLeg85j0pxVVFQEtbW11rjZp8Y28pnRZJT6N5FU328kMOqHVFNTE8477zx873vfi9o42Zp1kQeMHhYMdCUT9gc/+IGzj/b2djz88MP4+9//HrWRDa2saD7Yyg0hf0VLOzU3NzsNimPHjsXPf/5zi4fELJY///nPozamTNHAWgZocrMm5VSfMGECZs6caaXb4MbWh4v8IeVOcSx77rln1Lbbbrs5xzJx4kTMnj07KiUGxPwaPYS5IV1loD7zmc9EbcaYIf20t7fj3nvvxYwZM6I2vqz0vskE17zuzBJ6yCGHDNsHELLhf/SjH0VZUoE4m6Ue2MyeqTwoPtD6UnjzzTed/dTV1eHUU0+1Ang5V8pC52GvnD/uYbK0L7nkElcXmDBhAm644QZrf5D/pUHePJCUf8h70FqTSXNWW1uLk046yQrK5rOiaXS45/Tg4nrpy+ywww778Nbdy2Qy6O3tterIMSxFU+j+4Q9/AGA/YPvssw+AOEVrkpE/k8mgq6vLkqRIANVTnwuiIRncZK6KsbkoKSlBU1OTlbeKG183EN/YGvZD8l4+oh1T7uo98vdU+mCokKv2mZIik8C6a3qIkxioDwjvg4cGEK+Lji+pj9dff906ALiWSp4lSVHXig+ARt/nwze+8Y3ob5I4b7vttqiNRFI9PPjAFVKIYd26dbj33nstrYAHtY6R88jagUB8aPJwSQqLYhiZSuYMkdH9T6KzPkPcH0mpqV1QYuuZZ54JwCYDk6SsucMocRWyz0YC3ibl4eFR1PCHlIeHR1Fjs1SL2WabbXDMMcfEnWbFerVTMXKbMXdArIIxgZkaonORTqctlc1VfYaqg6pcNP4Wou6lUilUVlZa4jS/p6I47QRqOKV4zwwFSWPp7+/H8uXLLZWC96i/x3Fpelza8PKl9QVCW8OLL77ojLZXOw5rq+mcMc5NjbZJY1m2bJl1j1Rj1NBM+5r2y/UrtPJNfX29VZGIY9F6iLTtaDUc3kchFVaYcpeqGxDbmmiHBOIxajYFxrvRHppv7lT95N7SZIS8bzUL0L5WSMn4np4ePP3005ZaecIJJwCAFc9J9VzjIqkib4pa+e/AS1IeHh5Fjc2SBaG+vt56czBaW3M98S2hb2xGyvM6l5GYfVRXV1tR53TRqoGWbwX1IFJKKcRAy2wL6mXj27+9vT1q49vJVV2WRseksfBtrcZLRqertMc3reZdoufI5SLORWdnJx588EHrWnpbNW8R0yJrQQtKg5rlwYXu7m48/fTT1hrQA6VvexqdVXrkWqn3KgmsxqweURYVUC8ijc069y5nShLKy8ux7bbbWt4zGuHVccK9p5kMKA0lZb8g0uk0amtrrZxl9AjrWr3yyisA7Dxf/LwQraC3txcLFy609jK/r88q/543b17URom10IIf/y68JOXh4VHU8IeUh4dHUWPU1b3+/n6sWLHCqlVGdU/5KuTcqDGORluqZ0kpV1n+Wrk8NEyz0gwQi8GaUI5ivtZIS4IxBuXl5Za6QOOoqq5U91QcJhkuicSpY6murraSsFH101LevF+9jgx+NVQnobOzE/fff79FoOT8UJUAYhVgypQpURtVBFULk/p44IEHLDWOa6S8IqrMyh0i10hV+CRkMhn09PTgN7/5TdTGNVC1ksZmXT+uixqLVbVRVFZWYuedd7acQCyHrkZtGtE1YR/XSyMOXGC1GOXiUSXVvcw51VTRNI8Usv6pVAo1NTWWcZ+mFmWsc1+ryl5IjcqRhJekPDw8ihqjLkmx6q/WDCOLVdOh0sCpaWX5Rj/ooIMADG90HBwctN4ATGeqLna+xTWlLA3QGh6ShIGBAaxcudJK7s83o9b3ozFTY9sYSvLwww8P2wcrPqtLnPeoc0i2r8Y/8u2sElcSysvLMXnyZMvYzDlQIzAN8yql8u2tYUhJY2lpabF+j29klQCYglcNwzTKq4SaBKb1nTNnTtTGtND61qcUq31PmzYNgB32kSRJcW3UucNoAN17hF5HqZMSohr0cxEEgUUjofNC6QKcM3Us8Ll66KGHEn+bqKqqwpQpU/Dggw9GbdxzqrHwfnV+uK83JU3xvwMvSXl4eBQ1/CHl4eFR1Bh1dY/lvFUcZpl1NQ7SyKhMbBq4qWokGexYQ0y5TlSRNOUFVSM1XjNyXlWSJNBAq6DYrSoEf18Z1IUYM4HQeNzQ0GA5Gtinsn45N6oWMjq/EHG/paUF3/72t/GrX/1qSD9a34/sajWwkgWez4A6ZswYfPGLX7Tum1A1lftB1RmOS9XoJDASQLlF3Fua0YFrTJY4EGe/SHLKKBj8reo0q/a4HC+6J2h2cPG3FKwhqBEMVJGVv+QqTX/PPfdYfQ0H8hd1j1Kt1CwRvE81kZAzVwizfSTgJSkPD4+ixmarYKxS0wUXXADAdi/TpaquTkokfGPff//9w/ajcV58E2u6DJ78Gs/Ft44aBvO95fSNzzeMsthJo3jiiSeiNr7FGbvlki6A+A2nxls6DChxAHH+Lc1tRMPpcEZZoqGhAcccc4w135xfTR5HuoGOhS58pS+4UFNTg7333huf/vSnozbGYSoNgFK0zgkN9kpTSUIQBMhkMjjiiCOiNq7L448/PuR6Vp0GYkmtkLQjpaWlGDduXJTyBQD+9Kc/RfdAUOJxUSq0PmPSWPr6+iwaCCkIyi6ntKM5tOhkKGQvp9Np1NXVRelZgNjhovuMaZWYngeI995wsbQjCS9JeXh4FDX8IeXh4VHU8HX3Prh+tqSxOPvZksYyCv1sSWNJ7Gck4OvueXh4FDW8uufh4VHU8IeUh4dHUcMfUh4eHkWNUedJ1dbWBs3NzVZwMPkwyuEg41czQOYWeFyxYgU6OzuHUIOrqqqCuro6q6QVeS9aY4+cGK01Rj6Vclree+89Z6HDmpqaoLm52eLUkPGrzGYGYCrjmLY/jvO9997D2rVrh4yFBTX1HnMLi+r9asoPpj9RlnZS0caGhoagpaXFCurlPWq2Rv6+cpj4t7LQAQzpZ8yYMcFWW21lsaI5Lv0ux6W8G86x7pv+/v7EsbS2tlrcK86Fq6ip/iY/V55bUkHN0tLSoKKiwllaTdfaxZPKXf/3338/cS/X19db2TU5FxoJwPnTMfMedHxLly4ddv1dc65rw/2hKZS4hhpxsG7dug9vcdDm5mZceumlFqWf0epKquTnWoiBZE9uoPPPP9/ZB0lpjz32WNTGvzU5P4mdSvokWVA32WWXXeb0ejQ3N+OSSy6xiI3MHKDJ/U888UQAwIEHHhi1cWG56Oecc45zLO3t7bj//vute2QaYt18JOzpZn777bcB2OFGRx55pHMsLS0tuO666yyCIDciQzeAmACrGQYYOZ+TpnZIP1tttRUeeeQR3HTTTVHb0qVLAdgHEudEixkwi4UeHkuWLHGOpbW1FTNmzLBCm0hs1KKmJClqG3+f2RCA5IKaFRUV2G233awXCLHvvvtGfzP/l947D3uO9eKLL3Z1gfr6epx11llWxgvuZSVe8hDW8CnmZNNQlwsuuCBx/X/3u99ZITAMi9GXFMOXNOMBybeaMvvuu+/+8BYHNcagpKQk2nRAvBm/+MUvRm1cUD1o2MZ0FDlvbquPdDodVbEAYqasspApYbjSaiQVa1QMDg6is7PTio3i5tO+yeLWh5OVOCjZJfXHtCOasoYPnx6k/B09uJjeRGPTksB4N40p5IbVmCy+PJjcDYgPGE3Vohub6O3txaJFi6w+WNVZ14BrpbF3TGmjD1wSMpkMuru7rZzrTEHjSgek88gDXaXwJAwODqKjo8O6d86FHuLsU18WXO98SQ+BcD9rH9w7mludc+rSRgrdy93d3VbqIL7ktEAv9zdfLkD8XCbl6R9peJuUh4dHUcMfUh4eHkWNUVf3giDAwMCAJbafcsopAOwAYwaeqo7MDJhMh5IEqnsaGEljswaD0nDK0kbAphU4ZLkpBe0TmknRVYKLY6ZamFR2at26dZg9e7Zlk2D+bM3CyMBZNV5yvtQ+NtxYBgYGojzyet+qDtH2pW20uej45s6dO6SPvr4+LFq0KFLxgHg9Pv/5z0dtDAZWVYhj1iDmpOypvb29eOONN6y9Q+ieoAqoaWIYyOyyM+WipKQE48ePd6q2muGUaVvOOOOMqI37Jl/pLO4xzYRKM4WmiOHcq92LtkuXOSMXLNyqc051UdeV9kk1cdDOq3ndC0kP9K/CS1IeHh5Fjc2W9G633XaL2igRaMoTeik0NQfd+q5iiwoW7VTjNSUMfUPyb61eQsOzeiqSQCeAvr0oQSkFgcZmldjo3uVnSfna16xZg5tvvtkpeapXigZPvRcazDXVShK4Lmp4pcdIKRb8XA3QHINKwi5JilD6AtdAqRP0ZGoFGe4DHXMSOjo6cNttt1n74/jjjwdgp1Bhn5oIkfemKWvyQfeoq9gp10RTplC6oQctCdxjSjeg5Kf0HM6VOi84t4U4TphckfcPxE4K9SxTqtLkiuxbDfmjCS9JeXh4FDX8IeXh4VHU2Cw8qfLycov5zfzcrqyZKlaSQMYslcNlTzTGWEZSivaqchGqmtDYqGJvElz52imC632TIKn3Q1AFSOKy9PT04KmnnsKxxx4btVG9eOutt6I2qnSaMZGGTC2llQQWVNXyXDRSqxGYfC0lSpJ7psZ0F8rKytDe3h4Z2oF4/MqKpxNA1TBmz1Q1MwksdKp5uMn5UcKpK286910hBS9TqRSqqqosJwl5UkpW5t5TswL3OlWqJHWf6p6rVJmOj99/5JFHojaq5jqPSSgpKcHYsWOt54OEVDU18Jm78MILozaqxnx2RhtekvLw8ChqbBYKQl9fn2XAJvtcjaJ0uaoxlu5xhqEksYKZe1x/jy5TZW7zc5UKKBW53Mq5MMagrKzMkqRYhFKpCXyT8TMgNtCSFZ30tqusrMQOO+xgsafpwtd83ZQAtDw437Q54SpOsPLNUUcdFbWRIa1u6V//+tcAgPvuuy9qozFaJSQXWMpby5JTKtDKPr/97W8B2HQDSoja9q1vfcvZT1lZGVpaWizjN/eMSjiUNNXBQodHIRQERgNowVLOhVIL6NT42Mc+FrUxWoL7JCmPG6khuj/4e1q2neOixAjEEnehezmdTlthUZTONESIzi2Vmsk+L8RBMxLwkpSHh0dRwx9SHh4eRY1RV/eAUExWVe3mm28GYBuWyZ16+umnozaqOTTQDRfQyLJGBFUfF49EVQiqboWI++xH2eLvvBMGfyu3hMZ0FdkpSlMtSFL3xo4diy996UsWe5qqnwZ5MghUWb9EUrksBYNlc1KhALCN+lwjNbBSRcgX/Ev1WDlkNFCr0ZVOCw1iZpSBBh0nYdy4cfjmN79pqcM0jquRnGNQJwcdOspBSkIQBOjt7bXunXtS15M8ImWIkwe46667AkgOlgeG8gGphmsUAvfgHnvsEbVRjS3EcM5ged23jz766JD+uV5qfiAPS9d1NOElKQ8Pj6LGqEtSmUwG/f39ljGPbxEaTIH4jaQsXRoH6VpVlrKCxkZ9a37ta18DAKuMOL+vJbFpnC+kDDqZ7WpspASmeX1OO+00AHasHRnENDYmjaW+vh5HHXWUVcCSRmB9czF3kDLG6RAoVCoEbLoBC1eq1EtjtBrJKakpJcIFFqBUgzalEP0unSV77733kH4LKX9eVVWFPfbYw6K0UOpwzYVKwpSqCol3Y3oblTTpwFDplRIm41GBuIgn92WScZt7Wfv4+te/DiCm7gB28kSCVB1XyXfXWMrLyy1nEwuSnnfeeVEbpUKVHrmvveHcw8PDA/6Q8vDwKHL44qAfXD9b0lic/WxJYxmFfraksST2MxLwxUE9PDyKGl7d8/DwKGr4Q8rDw6OoMeoUhMrKyqCurs6ZOUBJZ4w307gzqqKkLHR3d2Pjxo1DfNLV1dVBY2OjFclON7DSEvh7GptG17GSGlevXu2sIVZZWRnU1tZacVquun0uoh7d3qRYrFmzBuvXr3fW3Wtra7Nc74y018RqHJe6kDl+nddXX301cSx1dXUWQZbueu2b66YxcK66cgsWLBjST1lZWVBRUWFRGlwkS/6t5FCulcaMvfzyy86xpNPpIJ1OW+Pmuuj3h1srJXguWbLE2U91dXXQ1NRk0Ud4n5qhg31q31wb9rN48WKsXr16yPrX1dUF48aNi0jCQLyempiRbXovJKbqnkiqIdjQ0BBMmDDBKi3Gv131HV1mIX1m3n333Q9v3b26ujqccsopVmbOs846C4B9WDCIUlNP8AEiV+Oee+5x9tHY2Iivf/3rVl5o8og0SyF/74YbbojaWIpIH5oZM2Y4DYq1tbU45ZRTcOONN0Zt5D8pY5mLrQ8NuVXTp08HAPz3f/+3cyxtbW248847LS4PS4Bpjm8y6g8//PCojeNXTsvuu+/uHEtdXR1OP/10zJ8/P2rjg6FzQQ6T8qTIk9FD5ZBDDhnST0VFBfbYYw+rTiFZ35ruhH9rpkc+FFrPbtttt3WOJZ1Oo6WlxaoNx2Bb7gMgZrZrNlMeLppt85vf/Kazn6amJpx//vnWy4IHu3KiyPdSBj0PGN7DQQcd5OoC48aNw+WXX44vf/nLURvZ3hdccEHUxjXWFwCDxQ8++OCoraSkxDmWCRMmYMaMGVatQ/6t68+50hcv97Uewt///vc/3HX3KisrrU3OUBXN63TllVcCgJXfiBuHEfNJJEWGX+jb8NprrwVgn/YMs3EtQr4E+UB4qM6YMcMi7nGz6ZuGh6pu/ClTpgCI8wrpPSjS6TRqa2utiHcWL9AwoqOPPhqAnU2AGR80F1ESNmzYgJdfftkKteAbVKP3+eDrYc9QlXzZFrq6ujB37lyrkAazG+jhyAOZcwTEYy0kz1N/fz+WLFli5QTjftMiEByD7kWSYQshwDIsRu+J2TZ0jHrAEJwrPuBJDqve3l68/fbb1guABXNV6uEzpGMmQXS4vGs6lkwmExF4gXhNNLMG1/+NN96I2viCLCTX10jA26Q8PDyKGv6Q8vDwKGpsFnWvtLTUEheZqOuaa66xrgPsiiGMQXJVE3H1c9ttt0X/zo06B+L4PDUWMx6qEBG5pKQEDQ0NVl07xtO5Yv80Qp22FYrISRHk/f39WLlypVX+mna6733ve1HbXnvtBQCYPXt21MbMCao2JWFwcBBr1661VGTaDVVNZYJCrZPHzAualcGFhoYGHHTQQZZtht/R2D2ORfuljS9ffCAQ2sZ22WUXS42jfU1jKplWWe1UjHdkfbnhQLOCxiJSxT7xxBOjNtoG1XbFuDiqZEnqZX9/P959910ceuihURtVX7Uf0U6l5gyuv+75JAwMDGDFihXWGtLEoDGQVIcZFwjExnSNsx1NeEnKw8OjqLHZ6u5ppdy7774bgO0dOOGEEwDYlVB5itPImGRspLSm3kIaY9WTQwlDpTq+ibTOWRJqa2vxqU99yrpvSoVa4ZXSiXqmmKuJb9CksWzcuBGvvPJK5HUEYpqEehBpMOcbGnBLj0ngm1SlQnrXGLGv/TCnERCvW1IxCWLs2LH48pe/bBma6QXT6H2us6ZbppG4kHp4tbW1mDZtmpUWmJKRShp0zetas5989fCAWJLS9MGUljSNL1Mta5YASlx0tCTlk0qn06ivr7fmlpQP9X5yL99xxx1RG6Xvk046Ke9YUqkUcikorowT1AY0vxmlL2b7GG14ScrDw6Oo4Q8pDw+PosZmSR8M2JwoGpnVoEqOhhryyBWhmK6GyFwEQWDV9qO6p+oQRX9VAWn8y5cKFwjVrTPPPNOpLkydOjVqI+dLjY1MWUzVJynpXU9PD5577jlLPaY6xPSuQOxUUDWF4no+NQyIa8hpWmCqqS51+KWXXoraqO5p8j8XqB6rKkyHgRpnqRbdf//9URvXT1nWSaipqcHUqVMtZwSNzJr2loZhNZKTt1RIcj3OmfKV+PvKx+L8aKUiqs10EiSpe5lMBhs3brRUSt6bqleMBFCeG/d6Icno0uk0ampqLAP+gQceCAD4whe+ELXRdKDjY5+FVCUaCXhJysPDo6gx6pIUE/5ryALfztrGt4DS/Pm25RtSDasKplxV1i/d2Wq0JZVh5syZURulNDUgJ4FOAA2/oQSmsYmkQmiSe0o+NO7newspk5jShL4hyZDXNLQcQyGG89LSUkycONFKP0wpVlMX8/fV/U2JVq9zobe3F2+99ZZlJOebW1ntXAOlG3B8hVAD2I9KdpTENOaQLG1lSpOdr3sxCdxnWhuSv68Sn6uWIyWpfHX3WFlYU2tTIlfHAPtVWg7Di4Yr8qBIp9NWFAPnTKkc1Dr0OeJ1hUQ2jAS8JOXh4VHU8IeUh4dHUWOzlFnv7++3DJNkeWs5Zxo11RBM8ZbBuJoZILePgYEBywhII/qxxx4btVHlUnWPPBE1uiehs7MTc+bMwU033RS1UfRXjhYN1/qbVF+WLVtm9ZuLmpoa7L///hYnimK1GtuZWUDr0tERoWpBEsrKyjBhwgSLkU2VRNUhqs1qyKdBWPliLnR0dOAvf/mL1QdVIOUvUeVUpwlVe+VnJaGzsxMPPPCA5fzgeqg6xDV47LHHojZ+XkjdPULnnCq2qlhUb9XAThMBHTVJzo2ysjJMnDjR2h+8VoOyuRdUzaTzptAaghs2bLDUTnLY9Bmk6qpVhdiPVkMaTXhJysPDo6ixWSSpgYGBKEUHELNz1XjMt6m6jOkKZ4qNJLc9EL7JNFHYgw8+CMB+2/PtxHgtIDbaar/DjaWvrw/XXXdd1EZJQ6U89qPufRqb2U9S7FZ5eTm23nprK/6O83Tvvfda9wIAxx13XNTG2DuNx0tCaWkp2tvbLSYx50Xd3656dDT+qnTlwoYNG/DKK69YrGjuA3UMcO3VaUJDbSGRAExvotQJSiw6F/xNlewoITD1zXBgqhY1iHP9dW9SiqNLH4glQjp31KCfC2MMTj/9dOvfQJwvCoj3m0p17KMQScoYg4qKCquWH6kiP/nJT6I2SoO6X+mYGS6WdiThJSkPD4+ihj+kPDw8ihq+7t4H18+WNBZnP1vSWEahny1pLIn9jAR83T0PD4+ihlf3PDw8ihr+kPLw8ChqjDoFgTXx1EWvRL7oRrKfaxkouqRJZlu3bh16enqGhKuPGTMmmDx5ckSUBGKXKVPGArHbXiusMG2wVm/ZuHHjsLXqNN6N/WgMFMegrmq6v0mJ6OjocNbdY901V507JTuyDyURkvqgc93V1eUcS3Nzc9De3u4kyGrlHP6+UhHoEtc5e+6554b009DQELS2tjpr++nvcT+4TA8aM/bKK684x1JWVhZUVlZa5El+T+eR963ZEnidpsJ99tlnnf3U1NQEzc3NVgwp6Ria+pjjUBc954r9rV69Gl1dXYk1JHWPucpucV10zC7S8/Lly4etIcn719/S55O/qWMh3ULr+yXVqhwJjPoh1djYiHPPPdc6LLhBlYVObocyt5kSgozr3//+984+Jk+ejHnz5uGSSy6J2vhAH3/88VEbJ5epVIA4h7dyml577bVha9VpLnUy5c8888yojVwoDY4l45hs3aS6e+PGjcMvfvELq7QXAz617hrnSQ9Ccn400Pahhx5yjqW9vR0PPPCAxU7netx8881RGzeuBi2Te6Rlrmpra4f009raihkzZli8JM6X8sDIFHcFxmow94477ugcS2VlJfbbbz+r9h2/p0HnvG9t43WshwgAFRUVzn6am5tx0UUXWTwivhi/+tWvRm18oDVgmmWgyGv68Y9/7OoiqiH517/+NWojA1xLZfGwf/rpp6M2BuRrxMCPf/zjxBqSJ598shX8zfJW+mJgPnsdC4WHT33qU1HbH//4xw933b3S0lLrbcqDQQliPNH1LcfDKV/k+ODgINatW2cRMvmgqnTFLAJ6OPK+Cokcz2Qy6Orqsh7Yc845BwAsUtwDDzwAIF5gIH4w+PZJCotIpVKorq623lLcsFp04dJLLwVgH1IsHqrE2SSQzKdz8Zvf/Mb6HcAOKyIoSWheLheYolhzHvGgUMIh101DPEj2LMSxs3HjRsyfP9+K3uccaN+UMLRABg/apDqICpJ5NfsDw6K0+C1TYOsBy795gA03LmOMJZlzjzEnGRATUpUUS0GgEDIvoWTnPffcE4C9l0m81oKzDIfxdfc8PDw84A8pDw+PIsdmSx+sujOTj6nYzBgyjbb+7Gc/CyBWDZJE5J6eHsseAcQqhIqzVG1UtaO4rzaJyy+/3NkPVSS9bxpcWSEEiGPaNLFboYnIjDFIpVKWDY+i9t577x210balZbKpUmyKGH711VdHfzM7hGYToNqsc89YQrU1ubB27VrcfffdkXoPxLY7TTLI+ota+5D2FTUWJ4FpijWFM+P4dN9RnVFViuYFNVQngdViNO0113/WrFlRGxMEauwek+rRxKEG61xkMhnL3kdo9g7er6qUNF3ky07BPjZs2GAZ2TnnmlxR1WWCNuWkrCQjDS9JeXh4FDVG/ShMp9Oora213P50n6vxmMY6zVDArAZ86yYZBDOZDHp7e62Ieb6p1GvHN42+SWmgLiRvEWuiqZRDqKubHhx90zALAp0Bw0lW6XTaomLQYKrGdBYt0Lp0WtygUNDbBsRvZc0TxDlTpwTzZOWrLtzV1YU5c+ZYb3ZG92sbf0+lCxqyh8t8QdTU1GDfffe1aASUyNU589GPfhSAvY+4LsNJNgSdGippco21jeulhUPobaahe7j1T6VSlgRJaU8dC/SwaeYHFx0mCb29vXjzzTet+yb1RLNg8G+mJgZiZw3rQY42vCTl4eFR1PCHlIeHR1Fjs1i+jDGWeEsDpxoWKQZr1Q6KyCQUJonIJSUlaGhosNQdGnyVmMbaYcqoZelq5dgkgaqrqgYU95UUSXFbk7hRNKaKm1TnLZVKoby83OqD96ZGUqosyg4nebSQyifpdBrV1dWWWsGxqEGchvkTTzwxauO95zOcU6XQNNFUyZVESNVOeVe8F12/JJSUlGDMmDFWbUBW6mGdOyBWWZTzw/tQcmkSyJNypX5WRwDX/5FHHonaWA2ptbU1bz/GGEu1pylB15/PhEYh0JheCE+qr68PS5cutVQ23pvWC+TeU1I0zR2+7p6Hh4cHNlP64L6+PsuoTfa1VkrlG3PGjBlRG43oNCInURBKS0vR2tpqpQ+m0VINr48//jgAOItCqPs6CcYYlJeXW3FMDFlQxjLfSOrW5huL/08yCNM1rAZfzo2yyym5qcGekmYhFIRMJoO+vj4cdthhURurTKs7nTQKdSwwzaxKCi5UV1fjYx/7WMRaBoCHH34YgG3wp1NFJWFKnBomlYS+vj688847Vm1ASkvK0s6VZoF4T6lEkgSmwlbDMqVJpQzQWaN0mtwY0eEqJg8ODlpSCik7Kknx+1rbketeCEu/vLwc2267raWd8N7UyXX22WcDsCVprmcu7We04CUpDw+PooY/pDw8PIoao67uZTIZ9PT0WCIoDdjKbNUUFgSN6flqlaVSKdTW1lqMZZcRkZHoqlaQE5T027ljWb9+vSUiU23RktNU9zSIlmpZvmBpVw1BGuD/53/+J2qj00GdAFRZNChYg4Vz+8lVw3m/Oj9UXdRYzIBn1jFMQmNjI04++WQrawTVY+VdsQ+9F6q2mhYlCRs3bsRrr71m1aWj4VlTwtAcoOlNuFbKQUoCg+V17agiqQOD66WqOA3zvB9XuiLtx6UOPvroo9Hf3G8aDEy+WSHcsoqKCmy//faWw+f2228HAKuM/DHHHAPAXhvuM1clodGAl6Q8PDyKGpuNgqAMarKlNS8PJRk1xrLOWD7po6SkBM3NzRbTlpKUSgCMuVMWOo2bw73ZiIGBAaxZs8Z6a9KwqC5autLVGEujLu8rybXO2m7qJqfrXNPOMB+R0jj4t7KDk2CMQTqdttz2hKYd4fz97Gc/i9r+9re/AbANucquJmpra3HwwQdbkhm/q5IC3dzqkKC0nS8dDBCvixp8OQatIk3JXR0LlKQKqfpMrUClrs997nMA4rhAHYc6ckgPcSXeUwRBgEwmY33OPGkaCUCKhjogGCOp85AE7jPOMxDPy1lnnRW1cY31fqid+Ng9Dw8PD/hDysPDo8jh6+59cP1sSWNx9rMljWUU+tmSxpLYz0jA193z8PAoanh1z8PDo6jhDykPD4+ihj+kPDw8ihqbpThoQ0ODxQsi98XFFVKmNRnk5EmtWbPGWVCzoaEhaGlpsVjMhHI5+DvKxyHnQ7NtLlq0yFnosKSkJCgrK7O+T/a58kg4BmWmk31MJvS6deuwYcOGIWNhAVJlDfN3dG7I61L+GTk4Wndv8eLFzrHU19cH48aNs/hh5HDp+Dgu5TXxO/rdJUuWDOmnubk5mDhxovV7ZJJrGhtmh9RsnfxtZW0/88wzzrE0NTUFytkCYn6X9kP7q/bD/aGpcd56663EOWtpabHWlb+pwd9cO50z/s2xrly5EuvWrRuy/o2NjUFbW5u11rljUriK7uqc5SuoqjZpzoH2w+dD9xmhmVA7Ojo+vMVBGxoa8JWvfCVKqQsABx10EAA7sp4Lr4TFJ554AkAcGpFUULOlpQXXXnutFTainxH8HY3KJ4nvlFNOido+//nPO70eZWVl2HbbbS2SHiPrtZjnwoULAdjhFyTisaDiDTfc4BwLC5BqeBB/R0NEeMBrpgUSYjW7xNe+9jXnWMaNG4crrrjCSh971113AbBT0jILgr5QeHDpw3DeeecN6WfixIl44IEHrN9jwQ1mpABiku1+++03pA/N82WMcY5l4sSJmDVrlhXaxAwaSg7m4XHAAQdEbXw5KSnypJNOcvbT0tKCq666yjqQ+PByXECcZ0lDsniYsJjGueee6+oCbW1tuOWWW6zsBnw2NPuCK+MFQ3SU9LnTTjsNW1BVD2eSjzWFNwnSShDlYajFQW+99dYPb3HQVCqFqqoqK7ka48n4UPA6wK6IwgOEE5mU9G79+vV49NFHrTcAWeW6UTj5mtebD2khydWCIEB/f7/1cDJOTpOZMVZND0gWpKQUmRQrGASB9RAAcVyYHurc9Do+jqUQ9nQ6nUZTU1P0IgDiyip6YB955JEAgLvvvjtqI0tZq+EMNxY9SO+9997oM4IHhcZy8pAuJO1MKpVCXV2dFUtI9jWTzQFxOpXHHnssauO9qfSZBMbuqYTE1DOa752FSfVlyJhF3kNSTvXBwUF0dnZa0ierD2miQLLelf3OvVBI7F4qlUJFRYUlIfF7p556atTGvaRxg/xOIQn8RgLeJuXh4VHU8IeUh4dHUWOzBRhrkUFm39RAWIqqs2fPjtqOO+44ALGunUQ87e/vx3vvvRdl/ATi1BhqK6BorwHC/M6hhx6adxwsnaXpMZjbWlUNjkVVFYrq+VKC9Pb2YtGiRZZoT/VSVUT2p+oeU2ckBa8qenp68Oyzz1qpXJiqhWWngFgVU1Wb9gkN3k0ay9tvv22tKdfjhBNOiNoYnKwqN9faFbici/7+fixdujTKYAkA99xzDwA7lcmuu+4KAJg3b17URnVQA4SHgzHGyrjJ9DCqAvLedR3o1KGNTA36rj5UTaXdU+2H/G1VG7k/CilE29/fj5UrV1q2TxrCVfXlWqsphaaZQnKpjwS8JOXh4VHU2CySVCqVsozVlIxYchuI3ev/+7//G7VR8qERfLh0Kul02srXzUKQrsR6WkGEBm29bjhkMhlLEqMhWI2VrmKX/JvjTJIK6QRQ0MOlqV8oaalXkW9STfOShI6ODtx2222W541VXdQrSWO6VoYptDhkR0cHbr311shoDADbbLMNAHu+mDNdEweSquEqN56L7u5uPPXUU9FaAHHFHHUCUEJQTx73WCHSZzqdRl1dnbUP6f3SHPdcW+5BIHZ60Omgc6xgCh3OExDPmUo99PS6cusXsv69vb1YsGCBdR906ij9gRKUGvI5/kKk3JGAl6Q8PDyKGv6Q8vDwKGpsFnVvYGDAEhcpIquqwc81aybFynz5x0tLSzFu3DhngU7lHNGgqKI0RdxCSielUinU1NRYpDoatZU7RZKbGpZp9HQxuBXMo64MeP6OGtNp5NR81FSNVG1KQk9PD5555hmrdBI5U2p4pTqkjgHOs6oaLqxduxazZs2yCLok9Wq/vF8XMVULiyahq6sLc+fOxYMPPhi1UbXXtaKKpPdDFVDZ00kgt0yJyYyK0P19+OGHD/nNO++8E0Bcnmq48mwTJ060jNecqz//+c9RGzl/LG4LxMZ4qs/DYXBwcIiJg+uuZGWujRZPpfOnEBV5JOAlKQ8Pj6LGZqkW09fX53xTqQGSkoYa7ej+pHE4yXBeXl6Orbfe2srXTcaxGm1dLF8aBtV9nQRKbEotoISh973vvvsCgMWyZ6hMPgN9eXk5ttpqK+ttTaOrS5ohIxyIq+vkK3/OfrbZZhtLqnAVh6SLXWPjpk+fDsCuhuNCSUkJxo4da0lNlHBUOqb07KI5JDGzc5FKpSzJlUZkNQyTAa6ufK4VxwQA559/vrOPTCaDrq4uS8pxlZw/+eSTrXtQFJK/LZPJWOv/0EMPAbCpE5RwVHsgzYFVX4ZDaWkp2traLBoQoxg0CoF7+Etf+lLURqoL89WPNrwk5eHhUdTwh5SHh0dRY9TVPQblKmgg/fjHPx61sXCnis00FFNFSDI2p9Np1NfXR0UrgdgQrsZmGv/U4Mto/ELKABljUF5ebhVFpAiuJa2oQqgKyPuhoTVpLNXV1dhjjz0scZ+cH1VTaDBVLg7vS3lcSWhqasJpp51mXcvSUxoFT+OoZg5g1gLlG7kwfvx4fOtb37LKJrnUHapPVImB2OisaVWS0NDQgOnTp1vrSvVUHRpUh9Q5M3XqVAB2QdQksKSVsq9prNasBVSXlJnOIGHOHUtc5YKlpnQ/8nc0LQuN15qeiJk1aOoYDiwOqo4XrruaZs444wzrvoE4mDqf42Sk4CUpDw+PosaoS1IsGa2xSmQG69uLBmWmvgDit0U+IyrLrCvdgGxoZTbzLa4pNFzXJaG/vx/Lly+34gEpyXz3u9+N2mjoV5c6++E4k5wA6XQaDQ0NlpRC97YWAmXhVDVe03VcaJnt7bbbzoolJKOdLHMgjmlUwzIlOpUeXKitrcW0adOsnFCUPFXKIDVA3+B0AmjB1yRUVVVhypQplnGf9zZ37tyojQZ8lzu9EJY23fbqCKAUqBIJJSlNCUOJkEVLdQ8q6GhiMVkg3veMPdS2X/7yl1EbnT+bUrRT75FS89e//vWo7aSTTgJg7zM6qAqJERwJeEnKw8OjqOEPKQ8Pj6KGLw76wfWzJY3F2c+WNJZR6GdLGktiPyMBXxzUw8OjqOHVPQ8Pj6KGP6Q8PDyKGqNOQWCtOhe0moqLGEY3K/+/evVqZ9091kPTdKZ0j7rcpBqxzr+VoJlUd62xsTGYMGGC5eLl3yRpAnE8oJI5OQYtRdXd3T1kLM3NzUF7e7tF0mN1Dp0jUhiUjEnXuM53X1+fcyxjxowJJk+ebNEkeL8a78Z+dMykOGgU/DvvvDOkn7q6umDs2LEWdYTf0bkhPUXj+UjCVKrGwoULnWOpqakJmpqaLAIk54DJ84B4fpRI6yKLLlu2zNlPQ0ND0Nra6rxPnTPOqY6R98N5TKohyXVREjL3sJJ5OQZNPMh10X2SNJaqqqqgvr7eolPw+7p/+EzpPLnSVD/77LMf3rp7ZWVl2GGHHSymMf++6KKLojamGdHryBUih+UnP/mJs4+WlhZcc801VuAvN42yg7nYGqhLlrOWZ0qquzZhwgTMnDnTSoXCAE8NymR6EE15QdY4AzavueYa51ja29sxZ84cXHnllVEbN71mqeSGvemmm6I2BqJqYPOiRYucY5k8eTLmzZsXpRABYp6UcnS4EXXM3NiaP/ycc84Z0s/YsWNx2WWXRWMH4pzwyrFiJlJNT8PacfrAnHHGGc6xNDU14cILL8Svf/1ra3yAXRuO+cX1wGV0gB6G3/nOd5z9tLa24vrrr7cOPt6nsupZ/ksZ9AwSJ98oqYYk1+Xyyy+P2ngQsVSW3q8G+TJTpgYNJ42lvr4eZ599NubMmRO1cV3JUdO/999//6iNkSIaMVJeXv7hrbsHhIeDLizzOTFUAIg3ixIy+WbMZ9xnylXNeMCNr9Ia3xQq9ZAsmJTOVcEQH5W6br31VgDxAQHEbx89pPhmZHGJ4YpKvPvuu9bhSgKopg/mPWhEPsmQhSbiX758ufUm5YZXoiHJh0p25MOXj2jJ2m5M0QzED6k+1AwZ4h4AYglIC6ImwRiDsrIyK1L/mGOOAWDXWOSLgZ8BcQGG3JTNLjD8Sotv8v700GWeNL2OLw7ObRIxmUVFdI9yr+ic8cDVPGjso5BU2OvXr8cjjzxivUAYiqUSG7NkqMTNF00htSpHAt4m5eHhUdTwh5SHh0dRY9TVvdLSUrS2tlrxWxR1tbYYDYFa/YQiNK9PUpEGBwfR1dVl2WeoGml2ghdeeAGAO0FZIalQmfRMS44zml3tYRyLVi+hiMxsAnqviiAI0NfXZ4n7VCl0/FSHVLWjeqGJ0FTdUWzYsAEvvfQSZs2aFbWxPp6qKbwPVffobMg3Z8YYVFZWWvYsjkXnhvZArezypz/9CYBd3j0JJSUlaGxstNQ42lLUtkNbpNrSqO4WkjmA6qsmCuQe1fHQsH7QQQdFbVQnmXVD11cxMDCAVatWWUZ32jjVMUC7oRrOOZZCS8ZXVFRYa+2qSsNnRR05vPfhqjeNJLwk5eHhUdQYdUmK+ZHUyMqUtJrulW52fYMUGmVtjEFpaanlJqURUA3i/G01WtLTozmGkjAwMICOjg4rowO/p1HilE70N5m1gAZ0jjcXTPbvSgvryk+lY6bhVA37Sejs7MRDDz1kSRBqrCdoJNfPKBmpm9wFSh5qnKckoRLeeeedN+S+KaFQ+s3XT2VlpfVmpxNFnTOUbHT9+XkhWRCYbUMdGMwIoM6GI444AoC9xvyc/SStf2lpKVpaWixDNedK73u//fYDYGcx4HpocQb1OisqKyux4447OouF8PkEYiO83g/XpNCqz/8uvCTl4eFR1PCHlIeHR1FjsxnOlf9EvoeK96+//joAWKoU1RsyaJMMdeRJqfjJhHqq7lGF0qRwJMAp8S4J7EdVMXJFtOYbCZKaCI+kQorSSemDy8vLMWnSJItcSq6XiuFU95RlzzGzluBwYGlyNQKTZ6WiPdU8TWdMdS9ftRggXDN1VFC9UuOsa+2ZHE/T/yaB/LU77rgjamNiQjUZMEW1qpCsUVeIacEYg1QqZbH8yYnS+n7sW+eWhm6qvkmJCbnHVKWkIXznnXeO2qjSqeGc91KI4bykpATNzc1OdrnuKTqEVJ2lOaOQWoUjAS9JeXh4FDVGXZKiS1Xdp/xbT2IaAF0xQoW8TdPpNPbee+/o32Qv63dJF1BmOt9YWk15uD7q6uqsNxXd2kqnoERA2oH+TSlyOBZ9KpWyUivzravseUoiGofIz9XFngTWKlRjPKUlZSFTwlRJim5rTZnrwuDgINasWWP9HiUWSrBAPPcarkIJWMeXBDo0NMSH0plKGiw0oO5/3kchKYvYj+4pOitU+iA1Q9eQ+0xr57nAYh8K/lsN4lxrlchISzn44IOjtt/+9rfOfliNWyU2Ss3q5KIkpVIh9/p111037FhGCl6S8vDwKGr4Q8rDw6OoMerq3oYNGzB//nzL2EixXg3QNChquXOK4Keddpr1bxeCILC4LlTpWFcNiNVLFaepeqpKkgQGmLqY1lp15dhjjwUAJzeM/SQFmA4ODmLt2rWWeM1sEKoOMdJdHRIU97VqShLGjBmDL3zhC1ZgNLMQsK4a7weIo/iB2ACtNf9cCIIAAwMD1nxPmzYNgO0E4RjUOEt1VlXcpGBj9qOBsYxc0H7II9L147rl43wBoara3d1tmSRY5l65YLxPXWOqUjRUJ60/x6IMb1cNQqqx6uQgd+qQQw4paCzr16+3gpbpzNHoCc6p7keqyLpPRhNekvLw8ChqjLok1dfXh8WLF1uMZbquVQrgqayGRX7O2m9JLF26bdXVTSOqUgv4trz99tujNhqBN6WC8TPPPBO1cVx6b8z7RHY1EEsJfPMNlxrGGGPlvCL7Wt3klHqUbkBpVd+uSaiqqsLuu+9u1fejBOBKZaPOAkp0+YzNQRBgcHDQym/EmDrGiQExDUClaErZmhtL81zl9tPf3x9JNUBsPFbDMusJutZPcyhpTcDcfgYGBizDeWtrK4A4BhSI06hcddVVURv3F6MQNI2PIpVKoaqqyqqxyKgATSfD/aGOD1dV4+FQUlJiPZeUkHSfsY2OCCB2RmnfowkvSXl4eBQ1/CHl4eFR1PB19z64fraksTj72ZLGMgr9bEljSexnJODr7nl4eBQ1vLrn4eFR1PCHlIeHR1Fj1CkIVVVVQUNDg0WqY3pVddvzc1fCNl73/vvvo7Ozs6BaZSSmqaufqq2S/uhO17ZXXnklsVbdpEmTLBIb71sJiyTqadwZSXx0qS9btgxr1qxJHItW/HDFr3Es6mJ31V1bsmTJsHX3tB/Os2ZooDvaRZnQElQLFiwY0k91dXWQGynP+9bYvdy+9F5yPneOpbKyMqivr7coLaRRKEWD86Ouc+43bevu7nb209TUFLS3t1txeuxT3f78XPumq597P2kvV1RUBDU1NRY1gPete5S/o1kMuG46j0l198rKyoLKykpr/3DOlY6RWy9Q/9b6g88888yHt+5eQ0MDzj77bOvwYaoPZXlzQVlCScHrLr74YmcfrFX2X//1X1EbNwrTZgDxRtQSS+T/fPKTn4zadtppJ6dBcdKkSXjyySctTgwXkSxsIOZjKUeLfJof//jHAIATTjhh2LFozmweirqh+LDrIUOelHKQzj333MS6e08//TTuueeeqI0Hhz6EDJZWbhE36Yknnhi1HXzwwUP6aWhowFe/+lWrjQ/CzJkzh9yTHsaMHlCb6fr16xNryJ1xxhlWkDc5amS4AzErXLOCsnacBto++eSTzn7a29sxe/Zs6yHm/rr66qujNr6INNqB3Cse7N/+9rddXaCmpgZHH320xUviGugeZUZNjS7gXlSe20UXXeQcS2VlJfbdd1+LU8c51+eIY1UWOjlseginUqkPd929VCplhY3w0FGq/ZQpUwDYOZP4FubGTsr509PTg2effdaK/icBkpHvQCxhaLYEvg0Kqe+2evVq3HjjjZakwkXUNx9DcrSNhxjHkOSw6OvrwzvvvGM9cMzBpA8x36oqPTKUpJA8P319fViyZEmUGQKIw280ep8PtNaV44Z1SUOKdDqNhoYG60Hgw6qESD58momCB3whubGYPljXkIRh/T73kZI1uf6aRjcJJSUlGDNmjHUIsO6i7mUeTkqU5aHJAp9J+aS4LprWmYeGSjM8xDQ7Be+rkBqSDL9i+mMgDnPS8DKGWqnUzDktpJ+RgLdJeXh4FDX8IeXh4VHUGHV1L51Oo7a21hJvad/QeDDaohjHBcQiNFWDJBGZyeg00wLj+FScZdyUGlhp0ykkC4IxBsaYyI4BxOI2S5QD7iRutFPw+tzEZsTatWsxa9Ysqx4e702TnlGF0swBtBXkS0YHxDGVqg5TjNf54VjUJsUsD2qbccEYg5KSEisVMlVRVSkZ3a8pmDlPmjhQ7XQK1ipUFZLqtKp7VLm1ggrV2UIyB/T09OCFF16w7uOuu+4CYJsQuKdU3aNdiWuke0NBdU/VK9as1JTL/L6aAKiaFRK72dfXh2XLllkOCqrdmm2BMYdqrqGBPimTw0jDS1IeHh5FjVGXpMrLy7HNNttYhmC+/Q877LCojW8ijQ5n1LpKLi4wRbFKYTQIq/Ga3g/NlkBPlr6lklBWVobJkydb3kG+sefOnWvdDwDsuuuuURu9e3xzJ0WQr1mzBjNnzrQMsZRE1EhKl7e+9ZhtoJCiAiUlJRg7dqzlTeWbWDNCsB81xrtqDbrAeojqgaJzQ43kv/vd7wDYBlvOcSFOAPajUhMzUbCmHxDPzz/+8Y+ojWmrVVJIwooVK3DFFVdYnjc6EdT7RalaDctcJ85nUkYPSoXqWKEHVj3IlGbU8bEpdfAymQw6OzstiY35qDTfFvNW6X7kuvsKxh4eHh7wh5SHh0eRY7MYzuvr661kdjTWquGVxkZVNWiYyydWdnd3Y968eZgxY0bURs6Mqgv8Ww3DTB6maWqTUFFRge23395iZNNwqVVJKEKrcZicIqqkSRyT7u5uPPbYY1bqYToYVOSmWsykfUCsFmta5iRQ3VPCIb83e/bsqI0Gf6qrQKxOqlPCBaphqtqQaOpKe0wVTdsKqRZjjEFlZaUzkkBVUnLKdK2o5iWpX4qOjg7cfPPNloGefWpCOnK8WLEIGFqrMMlwXlZWhkmTJlnkZybz0/100UUXDfkdcrCUhZ6EIAgQBIE1FvLH1ERCNVW5YeSUaR3A0YSXpDw8PIoamyV98LJlyyzDNKUmNZJT+tBQErptedonSVRBEKC3t9d6Q9L4xzcY4GYhEyopJIFVX9UJMGfOHAB2WAUlAn2z0y18ww03AEg21FdWVmL77be3wl1IV3Cxy9UoTWOzuu2HG0tDQ4NlJOU96puYv6VGba4Lx56EwcFBdHZ2WvQOShzKVie1RCUFrpHSSpIQBAE2bNhgjYUUDqW5cAxabfi4444DUJj0UVpaipaWFsvYTGO87glKZSqlUoKkZJpUS5LOGZWaSY/QfctnR5nydAIlVcdWsO6iy9mkGg5DiXS9WJRDnQWjCS9JeXh4FDX8IeXh4VHU2Czq3pIlSyxRlSqYcjwo/mqVlNyUF0nqXl1dHQ4//HCL9c0+NKKfqoOmmKC4rkbOX//6185+jDEoKyvD/fffH7UxcFTFdzKEtRYbuVlU45IMwi0tLbjgggsiJjMQi/TqBCD7nPXlgLiySyFBuax8okxyOhuUw0VujrKYGfCcFAGgGBwctJwEnC9lY9P4q8Zi8qgK4XxlMhn09PRE/C0gVrkffvjhqI1qp2YT4PhUXUvChAkT8N3vftdSczjXVON1HDRkA7GKRFUwyXA+ODiIdevWWfXwyJNSpxJVf2W6q3khH0pKStDY2GhFPpDDpY4XPj/kLALxPtMqQKMJL0l5eHgUNUZdkqJRW6vd0tirzG++OfQNQxcnXaJJ6U0qKyuxyy674Oijj47aaAjVBHWUpJRdvNdeewGw2eH5xqP3zXtSAy2NjKy/BsSSEw2oScbNxsZGfOYzn7GkRtI31IhM46ZKGsxtVEhMFaVCNZxSulGJjX3+6U9/itooVSkD2oXBwUF0d3dbkhnnS/NJ0eCthmYauV3VonNBd7reN+ML1RFzwAEHALDzibGWnzoGklBbW4tp06ZZzH/+vkrsrPmn+4zrz72cJCEyHYze4/nnnw/ANu4zWkPzZVESKiR2j2l0yDIH4kgQV+JJpSAw9tFTEDw8PDzgDykPD48ih6+798H1syWNxdnPljSWUehnSxpLYj8jAV93z8PDo6jh1T0PD4+ihj+kPDw8ihr+kPLw8Chq+EPKw8OjqOEPKQ8Pj6KGP6Q8PDyKGv6Q8vDwKGr4Q8rDw6Oo4Q8pDw+Posb/B9vZiYpnZatPAAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<Figure size 302.4x288 with 100 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import ray\n",
    "import codeflare.pipelines.Datamodel as dm\n",
    "import codeflare.pipelines.Runtime as rt\n",
    "from codeflare.pipelines.Datamodel import Xy\n",
    "from codeflare.pipelines.Datamodel import XYRef\n",
    "from codeflare.pipelines.Runtime import ExecutionType\n",
    "\n",
    "ray.shutdown()\n",
    "ray.init()\n",
    "\n",
    "# #############################################################################\n",
    "# Setting up\n",
    "\n",
    "def nudge_dataset(X, Y):\n",
    "    \"\"\"\n",
    "    This produces a dataset 5 times bigger than the original one,\n",
    "    by moving the 8x8 images in X around by 1px to left, right, down, up\n",
    "    \"\"\"\n",
    "    direction_vectors = [\n",
    "        [[0, 1, 0],\n",
    "         [0, 0, 0],\n",
    "         [0, 0, 0]],\n",
    "\n",
    "        [[0, 0, 0],\n",
    "         [1, 0, 0],\n",
    "         [0, 0, 0]],\n",
    "\n",
    "        [[0, 0, 0],\n",
    "         [0, 0, 1],\n",
    "         [0, 0, 0]],\n",
    "\n",
    "        [[0, 0, 0],\n",
    "         [0, 0, 0],\n",
    "         [0, 1, 0]]]\n",
    "\n",
    "    def shift(x, w):\n",
    "        return convolve(x.reshape((8, 8)), mode='constant', weights=w).ravel()\n",
    "\n",
    "    X = np.concatenate([X] +\n",
    "                       [np.apply_along_axis(shift, 1, X, vector)\n",
    "                        for vector in direction_vectors])\n",
    "    Y = np.concatenate([Y for _ in range(5)], axis=0)\n",
    "    return X, Y\n",
    "\n",
    "\n",
    "# Load Data\n",
    "X, y = datasets.load_digits(return_X_y=True)\n",
    "X = np.asarray(X, 'float32')\n",
    "X, Y = nudge_dataset(X, y)\n",
    "X = minmax_scale(X, feature_range=(0, 1))  # 0-1 scaling\n",
    "\n",
    "X_train, X_test, Y_train, Y_test = train_test_split(\n",
    "    X, Y, test_size=0.2, random_state=0)\n",
    "\n",
    "# Models we will use\n",
    "logistic = linear_model.LogisticRegression(solver='newton-cg', tol=1)\n",
    "rbm = BernoulliRBM(random_state=0, verbose=True)\n",
    "\n",
    "# #############################################################################\n",
    "# Training\n",
    "\n",
    "# Hyper-parameters. These were set by cross-validation,\n",
    "# using a GridSearchCV. Here we are not performing cross-validation to\n",
    "# save time.\n",
    "rbm.learning_rate = 0.06\n",
    "rbm.n_iter = 10\n",
    "# More components tend to give better prediction performance, but larger\n",
    "# fitting time\n",
    "rbm.n_components = 100\n",
    "logistic.C = 6000\n",
    "\n",
    "# Training RBM-Logistic Pipeline\n",
    "\n",
    "pipeline = dm.Pipeline()\n",
    "node_rbm = dm.EstimatorNode('rbm', rbm)\n",
    "node_logistic = dm.EstimatorNode('logistic', logistic)\n",
    "\n",
    "raw_pixel_classifier = clone(logistic)\n",
    "raw_pixel_classifier.C = 100.\n",
    "node_raw_pixel = dm.EstimatorNode('raw_pixel', raw_pixel_classifier)\n",
    "\n",
    "pipeline.add_edge(node_rbm, node_logistic)\n",
    "pipeline.add_edge(node_rbm, node_raw_pixel)\n",
    "\n",
    "# create training input\n",
    "train_input = dm.PipelineInput()\n",
    "train_input.add_xy_arg(node_rbm, dm.Xy(X_train, Y_train))\n",
    "\n",
    "pipeline_fitted = rt.execute_pipeline(pipeline, ExecutionType.FIT, train_input)\n",
    "\n",
    "# #############################################################################\n",
    "# Evaluation\n",
    "predict_input = dm.PipelineInput()\n",
    "predict_input.add_xy_arg(node_rbm, dm.Xy(X_test, Y_test))\n",
    "#predict_input.add_xy_arg(node_raw_pixel, dm.Xy(X_test, Y_test))\n",
    "\n",
    "logistic_pipeline = rt.select_pipeline(pipeline_fitted, pipeline_fitted.get_xyrefs(node_logistic)[0])\n",
    "Y_pred = ray.get(rt.execute_pipeline(logistic_pipeline, ExecutionType.PREDICT, predict_input)\n",
    "                         .get_xyrefs(node_logistic)[0].get_Xref())\n",
    "\n",
    "print(\"Logistic regression using RBM features:\\n%s\\n\" % (\n",
    "    metrics.classification_report(Y_test, Y_pred)))\n",
    "\n",
    "raw_pixel_pipeline = rt.select_pipeline(pipeline_fitted, pipeline_fitted.get_xyrefs(node_raw_pixel)[0])\n",
    "Y_pred = ray.get(rt.execute_pipeline(raw_pixel_pipeline, ExecutionType.PREDICT, predict_input)\n",
    "                         .get_xyrefs(node_raw_pixel)[0].get_Xref())\n",
    "\n",
    "print(\"Logistic regression using raw pixel features:\\n%s\\n\" % (\n",
    "    metrics.classification_report(Y_test, Y_pred)))\n",
    "\n",
    "# #############################################################################\n",
    "# Plotting\n",
    "\n",
    "plt.figure(figsize=(4.2, 4))\n",
    "for i, comp in enumerate(logistic_pipeline.get_nodes()['rbm'].get_estimator().components_):\n",
    "    plt.subplot(10, 10, i + 1)\n",
    "    plt.imshow(comp.reshape((8, 8)), cmap=plt.cm.gray_r,\n",
    "               interpolation='nearest')\n",
    "    plt.xticks(())\n",
    "    plt.yticks(())\n",
    "plt.suptitle('100 components extracted by RBM', fontsize=16)\n",
    "plt.subplots_adjust(0.08, 0.02, 0.92, 0.85, 0.08, 0.23)\n",
    "\n",
    "ray.shutdown()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
